如何在 iPad 上使用 Javascript 打印 iFrame 的内容?

问题描述 投票:0回答:3

打印 iFrame 的内容似乎已经成为跨浏览器解决的一个具有挑战性的问题。在测试了很多方法(其中一些也可以在本网站上找到)之后,我当前的方法似乎在跨浏览器上运行得很好,如下所示:

function printUrl( elem, url ) {
    $( '#' + elem ).append( "<iframe style='border: none; width: 0; height: 0; margin: 0; padding: 0;' src='" + url + "' id='printFrame'></iframe>" );

    $( '#printFrame' ).load( function() {
        var w = ( this.contentWindow || this.contentDocument.defaultView );
        w.focus();
        w.print();
    } );
}

使用 iPad 时,此代码仅存在一个小问题。 iPad 打印包含 iFrame 的页面,而不是 iFrame 的内容。不过,Mac 上的 Safari 可以正确打印 iFrame 的内容。

有人已经解决了这个问题并能够在 iPad 上打印 iFrame 的内容吗?

javascript ipad iframe printing safari
3个回答
1
投票

好吧,首先。我没有解决问题。我创建了一个解决方法,实际上伪造了我想要实现的目标。

因为 iPad / iPhone 简单地打印父页面,所以我将完整的正文包装在一个新的 div 中,然后附加 iFrame 和一些样式表,以确保打印的文档仅包含 iFrame:

function printUrl( url ) {
    $newBody = "<div class='do_not_print_this'>"
                + $( 'body' ).html()
                + "</div>"
                + "<iframe style='border: none; 0; width: 100%; margin: 0; padding: 0;' src='" + url + "' class='printFrame'></iframe>"
                + "<style type='text/css' media='all'>.printFrame { position: absolute; top: -9999999px; left: -99999999px; }</style>"
                + "<style type='text/css' media='print'>.do_not_print_this { display: none; } .printFrame { top: 0; left: 0; }</style>";
    $( 'body' ).html( $newBody );

    $( '.printFrame' ).load( function() {
        var w = ( this.contentWindow || this.contentDocument.defaultView );
        w.focus();
        w.print();
    } );
}

在普通视图中隐藏浏览器的 iframe 是使用绝对定位完成的,使用无显示或可见性隐藏在最终打印中引入了奇怪的行为。

是的,它很丑。然而,这是目前我能想到的唯一可行的选择。如果大家有更好的解决方案,请告诉我。


1
投票

这是一个在常青浏览器和当前版本的 iOS 上跨平台工作的功能:

function printElement(divid, title)
{   
  var contents = document.getElementById(divid).innerHTML;
  var frame1 = document.createElement('iframe');
  frame1.name = "frame1";
  frame1.style.position = "absolute";
  frame1.style.top = "-1000000px";
  document.body.appendChild(frame1);
  var frameDoc = frame1.contentWindow ? frame1.contentWindow : frame1.contentDocument.document ? frame1.contentDocument.document : frame1.contentDocument;
  frameDoc.document.open();
  frameDoc.document.write('<html><head><title>' + title + '</title>');
  frameDoc.document.write('</head><body style="font-family: Arial, Helvetica, sans; font-size: 14px; line-height: 20px">');
  frameDoc.document.write('<h1>' + title + '</h1>');
  frameDoc.document.write(contents);
  frameDoc.document.write('</body></html>');
  frameDoc.document.close();

  setTimeout(function () {
    window.frames["frame1"].focus();
    window.frames["frame1"].print();
  }, 500);

  //Remove the iframe after a delay of 1.5 seconds
  //(the delay is required for this to work on iPads)
  setTimeout(function () {
     document.body.removeChild(frame1);
  }, 1500);
  return false;
}

这是基于 this 答案 进行了一些小的修改(重要的是,必须删除

document.body.removeChild(frame1);
行以允许在 iOS 上打印。)


0
投票

我使用了@d13答案并做了一些修改。因为

window.frames["frame1"]
不是一个有效的对象。 window.frames 是一个类似数组的对象。

MDN 文档

返回窗口本身,它是一个类似数组的对象,列出了当前窗口的直接子框架...

window.frames 伪数组中的每个项目表示与给定的 或 的内容对应的 Window 对象,而不是frame或iframe DOM元素(即window.frames[0]与document.getElementsByTagName相同("iframe")[0].contentWindow).

所以我使用了以下方法:

export function printHtml(html: string) {
  // Create an iframe element
  const iframe = document.createElement('iframe');
  iframe.style.position = 'absolute';
  iframe.style.width = '0';
  iframe.style.height = '0';
  iframe.style.border = 'none';

  // Append the iframe to the body
  document.body.appendChild(iframe);

  // Write the content to the iframe
  const doc = iframe.contentWindow?.document;
  if (doc) {
    doc.open();
    doc.write(html);
    doc.close();
  }

  // we need to use the print this way to be able to print in phones
  setTimeout(() => {
    window[0].focus();
    window[0].print();
    setTimeout(() => {
      document.body.removeChild(iframe); // Clean up by removing
    }, 500);
  }, 500);
}
© www.soinside.com 2019 - 2024. All rights reserved.