简体   繁体   English

Twitter Bootstrap:打印模态窗口的内容

[英]Twitter Bootstrap: Print content of modal window

I'm developing a site using Bootstrap which has 28 modal windows with information on different products.我正在使用 Bootstrap 开发一个站点,该站点有 28 个模式窗口,其中包含有关不同产品的信息。 I want to be able to print the information in an open modal window.我希望能够在打开的模式窗口中打印信息。 Each window has an id .每个窗口都有一个id

<!-- firecell panel & radio hub -->
           <div class="modal hide fade" id="fcpanelhub">
              <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal">X</button>
                <h3>5000 Control Panel & Radio Hub</h3>
              </div>
              <div class="modal-body">
                <img src="../site/img/firecell/firecell-panel-info-1.png" alt=""/><hr/>
                <img src="../site/img/firecell/firecell-panel-info-2.png" alt=""/><hr/>
                <img src="../site/img/firecell/firecell-radio-hub-info-1.png" alt=""/><hr/>
                <img src="../site/img/firecell/firecell-radio-hub-info-2.png" alt=""/>
              </div>
              <div class="modal-footer">
                <a href="#" class="btn" data-dismiss="modal">Close</a>
              </div>    
           </div>

So if I add in a new button in modal-footer - 'print', and it's clicked I want that modal to print.因此,如果我在modal-footer添加一个新按钮 - “打印”,然后单击它,我希望打印该模态。 Would I be right in saying javascript would be used?我说 javascript 会被使用是对的吗? If so, how do I tell javascript to print only the open modal, and not the others?如果是这样,我如何告诉 javascript 只打印打开的模式,而不是其他模式?

All help appreciated.所有帮助表示赞赏。

Another solution另一种解决方案

Here is a new solution based on Bennett McElwee answer in the same question as mentioned below.这是基于Bennett McElwee在下面提到的同一问题中回答的新解决方案。

Tested with IE 9 & 10, Opera 12.01, Google Chrome 22 and Firefox 15.0.使用 IE 9 & 10、Opera 12.01、Google Chrome 22 和 Firefox 15.0 进行测试。
jsFiddle example jsFiddle 示例

1.) Add this CSS to your site: 1.) 将此 CSS 添加到您的站点:

@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 2.) 添加我的 JavaScript 函数

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.只需使用您的元素调用printElement()并在完成后执行window.print()

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/注意:如果您想在打印之前修改内容(并且仅在打印版本中),请查看此示例(由评论中的 waspina 提供): http : //jsfiddle.net/95ezN/121/

One could also use CSS in order to show the additional content in the print version (and only there).还可以使用 CSS 来显示打印版本中的附加内容(并且仅在那里)。


Former solution以前的解决方案

I think, you have to hide all other parts of the site via CSS.我认为,您必须通过 CSS 隐藏网站的所有其他部分。

It would be the best, to move all non-printable content into a separate DIV :最好将所有不可打印的内容移动到单独的DIV

<body>
  <div class="non-printable">
    <!-- ... -->
  </div>

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

And then in your CSS:然后在你的 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?致谢Greg已经回答了一个类似的问题:仅打印 <div id="printarea"></div>?

There is one problem in using JavaScript : the user cannot see a preview - at least in Internet Explorer!使用 JavaScript存在一个问题:用户无法看到预览 - 至少在 Internet Explorer 中!

I would suggest you try this jQuery plugin print element我建议你试试这个 jQuery 插件打印元素

It can let you just print the element you selected.它可以让您只打印您选择的元素。

With the currently accepted solution you cannot print the page which contains the dialog itself anymore.使用当前接受的解决方案,您无法再打印包含对话框本身的页面。 Here's a much more dynamic solution:这是一个更加动态的解决方案:

JavaScript: 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: 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 -->

Here's an option using a JQuery extension I made based on the code by waspinator in the comments of the accepted answer:这是一个使用 JQuery 扩展的选项,我根据已接受答案的评论中的 waspinator 代码制作:

jQuery.fn.extend({
    printElem: function() {
        var cloned = this.clone();
        var printSection = $('#printSection');
        if (printSection.length == 0) {
            printSection = $('<div id="printSection"></div>')
            $('body').append(printSection);
        }
        printSection.append(cloned);
        var toggleBody = $('body *:visible');
        toggleBody.hide();
        $('#printSection, #printSection *').show();
        window.print();
        printSection.remove();
        toggleBody.show();
    }
});

$(document).ready(function(){
    $(document).on('click', '#btnPrint', function(){
        $('.printMe').printElem();
    });
});

JSFiddle: http://jsfiddle.net/95ezN/1227/ JSFiddle: http : //jsfiddle.net/95ezN/1227/

This can be useful if you don't want to have this applied to every single print and just do it on your custom print button (which was my case).如果您不想将其应用于每个打印件,而只是在您的自定义打印按钮上执行此操作(这就是我的情况),这将非常有用。

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.这是一个修订的解决方案,也适用于使用 Grails 模板渲染的模态窗口,您可以在同一主体中多次调用相同的模态模板(使用不同的值)。 This thread helped me immensely, so I thought I'd share it in case other Grails users found their way here.这个线程对我帮助很大,所以我想我会分享它,以防其他 Grails 用户在这里找到他们的方法。

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.这导致多个 printSection div 被创建并打印在彼此之上。 Therefore I had to revise the js to clean up the div after it was done printing.因此,我不得不在完成打印后修改 js 以清理 div。

CSS CSS

I added this CSS directly to my modal gsp, but adding it to the parent has the same effect.我将此 CSS 直接添加到我的模态 gsp 中,但将其添加到父级具有相同的效果。

<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.将它添加到站点范围的 CSS 中会杀死站点其他部分的打印功能。 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?我从ComFreak接受的答案中得到了这个(基于Bennett McElwee 的答案),但它是使用 ':not' 功能从fanfavorite 's answer on Print <div id=printarea></div> 修改的? . . I opted for 'display' rather than 'visibility' because my invisible body content was creating extra blank pages, which was unacceptable to my users.我选择了“显示”而不是“可见性”,因为我不可见的正文内容会创建额外的空白页面,这是我的用户无法接受的。

js js

And this to my javascript, revised from ComFreak 's accepted answer to this question.这对于我的 javascript,从ComFreak对这个问题的公认答案进行了修订。

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.我不需要附加元素,所以我删除了那个方面并将函数更改为专门打印一个 div。

HTML (gsp) 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!我希望能帮助别人!

I just use a bit of jQuery/javascript:我只是使用了一点 jQuery/javascript:

html: 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: 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这是小提琴

Heres a solution with no Javascript or plugin - just some css and one extra class in the markup.这是一个没有 Javascript 或插件的解决方案 - 只有一些 css 和标记中的一个额外类。 This solutions uses the fact that BootStrap adds a class to the body when a dialog is open.此解决方案使用 BootStrap 在打开对话框时向正文添加类的事实。 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".为了确保我们可以确定页面的主体,我们需要在 div 中包含主页内容中的所有内容 - 我使用了 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.然后在我们的 CSS 打印媒体查询中,我使用 display: none 隐藏我不想显示的所有内容 - 即打开对话框时的 mainContent 。 I also use a specific class noPrint to be used on any parts of the page that should not be displayed - say action buttons.我还使用了一个特定的类 noPrint 用于页面的任何不应显示的部分 - 例如操作按钮。 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;
    }
}

I was facing two issues Issue 1: all fields were coming one after other and Issue 2 white space at the bottom of the page when used to print from popup.我面临两个问题问题 1:当用于从弹出窗口打印时,所有字段都一个接一个出现,并且页面底部的问题 2 空白。

I Resolved this by我解决了这个问题

making display none to all body * elements most of them go for visibility hidden which creates space so avoid visibility hidden使所有身体都没有显示* 元素中的大多数都隐藏可见性,从而创造空间,因此避免隐藏可见性

    @media print {
        body * {
           display:none;
        width:auto;
        height:auto;
        margin:0px;padding:0px; 
        }
        #printSection, #printSection * {
            display:inline-block!important;
        }
        #printSection {
            position:absolute;
            left:0;
            top:0;  
            margin:0px; 
            page-break-before: none;
            page-break-after: none;
            page-break-inside: avoid;      
        }
#printSection .form-group{

      width:100%!important;
      float:left!important;
      page-break-after: avoid;
    }
#printSection label{
        float:left!important;
        width:200px!important;
        display:inline-block!important;
      }

#printSection .form-control.search-input{
        float:left!important;
        width:200px!important;
        display: inline-block!important;
      }
}

you can download printThis lib from this source https://github.com/jasonday/printThis/blob/0a7f799693af8a8303bf0b8df0efc80c2694af81/printThis.js and include it into your html page你可以从这个源https://github.com/jasonday/printThis/blob/0a7f799693af8a8303bf0b8df0efc80c2694af81/printThis.js下载printThis库并将其包含到你的html页面中

Call the following jquery to print all the content including the content that is not viewable.调用以下 jquery 打印所有内容,包括不可见的内容。 You may include your css files in an array if you have multiple css files.如果您有多个 css 文件,您可以将 css 文件包含在一个数组中。

$("#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          
}); 

So I have a react app that lives as a webcomponent on multiple legacy sites.所以我有一个 React 应用程序,它作为多个遗留站点上的 webcomponent 存在。 None of these solutions were exactly what I was looking for.这些解决方案都不是我正在寻找的。 There are downsides to the accepted answer.接受的答案有缺点。 Say we have this CSS:假设我们有这个 CSS:

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

body * {visibility : hidden} will prevents users from printing the page if they hit CTRL+P. body * {visibility : hidden}将阻止用户按 CTRL+P 打印页面。

This also doesn't account for multiple print UX workflows as well, incase a user might need to print a page off a modal and a drawer that are on the same page.这也没有考虑到多个打印 UX 工作流程,以防用户可能需要从同一页面上的模态和抽屉打印页面。 That's a rare case but again this isn't accounted for这是一种罕见的情况,但同样没有考虑到这一点

The solution解决方案

The solution I chose instead is to apply a top level CSS class on the body.我选择的解决方案是在主体上应用顶级 CSS 类。 In my React Modal component, I use a useEffect call在我的 React Modal 组件中,我使用了 useEffect 调用

import React, { useEffect } from 'react'

export const ModalPane = (props) => {
  useEffect(() => {
    const body = document.querySelector('body')
    if (body) {
      body.classList.add('hide-on-print')
    }
    return () => {
      if (body) {
        body.classList.remove('hide-on-print')
      }
    }
  }, [])

  const handlePrint = () => {
    // add any prework or analytics tracking here etc
    window.print()
  }

  return (
    <div className="print-me">
      <h1>Modal content stuff here</h1>
      <button type="button" onClick={handlePrint}>Print</button>
    </div>
  )
}

Once this modal is rendered (aka the user is looking at the intended modal), only the contents of the modal will be printed.一旦呈现此模态(也就是用户正在查看预期的模态),只会打印模态的内容。 It doesn't matter if they hit the print button or press CTRL+P他们是按下打印按钮还是按下 CTRL+P 都没有关系

This applies a class called hide-on-print on the body element.这在 body 元素hide-on-print应用了一个名为hide-on-print的类。 This media style then get applied, which is scoped specifically for this print UX instance (you can add more classes to body for other specific print queries)然后应用此媒体样式,该样式专门针对此打印 UX 实例(您可以为其他特定打印查询向正文添加更多类)

@media print {
  body.hide-for-print {
    visibility: hidden !important;
  }
  body.hide-for-print .print-me {
    visibility: visible;
  }
}

TLDR TLDR

use a react useEffect component that applies hide-for-print class only when its rendered.使用反应 useEffect 组件,该组件仅在渲染时应用hide-for-print类。 Wrap the @print media query behind this class.将@print 媒体查询包装在此类后面。 This handles all intended UX print use cases and can scale to any other specific print UX cases这可以处理所有预期的 UX 打印用例,并且可以扩展到任何其他特定的打印 UX 用例

 @media print{ body{ visibility: hidden; /* no print*/ } .print{ visibility:visible; /*print*/ } }
 <body> <div class="noprint"> <!---no print---> <div class="noprint"> <!---no print---> <div class="print"> <!---print---> <div class="print"> <!---print---> </body>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM