关于新附加的HTML的Javascript window.print()问题

Javascript window.print() issue on newly appended HTML

本文关键字:print 问题 window Javascript 于新附 HTML      更新时间:2023-09-26

问题是新内容将无法打印(更多元素)。

当用户单击我的打印链接时,我会在调用window.print()之前向文档添加更多html。

在打印之前,我使用ajax为一本书获取更多章节。

代码:

打印已初始化:

var afterPrint = function () {
  var timer = setInterval(function () {
    afterContentPrint(); // Cleanup html (restore to initial state)
    clearInterval(timer);
  }, 900);
}
//window.onbeforeprint = beforePrint;
window.onafterprint = afterPrint;

事件打印点击:

$("#print-test").click(function (e) {
   e.preventDefault();
   beforeContentPrint(); // ajax call for additional content, finishing by calling window.print()
});

在函数beforeContentPrint()中:

var jqxhr = $.ajax({
   type: "GET",
   url: bookURL,
   success: function(data) {
     .....
     .....
     $(article).each(function () {
        parent.append(article);
     });
   },
   complete: function() {
     var timer = setInterval(function () {
        window.print();
     }, 900);
  }
 }

新内容被明显地添加到HTML文档中,因此它应该可以工作。但只有初始内容(在ajax调用之前)会被提取出来进行打印。

此解决方案适用于IE和Firefox(onbeforeprint和onafterprint)。

使用window.matchMedia("print")似乎可以在Chrome中使用这种逻辑。

我不知道为什么会发生这种情况,但在mozilla文档中有一个解决方案;打印一个隐藏的iframe,然后你就可以打开书中的更多章节,而无需显示。这里是链接https://developer.mozilla.org/en-US/docs/Printing

这里的代码:

<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>MDN Example</title>
<script type="text/javascript">
function closePrint () {
  document.body.removeChild(this.__container__);
}
function setPrint () {
  this.contentWindow.__container__ = this;
  this.contentWindow.onbeforeunload = closePrint;
  this.contentWindow.onafterprint = closePrint;
  this.contentWindow.print();
}
function printPage (sURL) {
  var oHiddFrame = document.createElement("iframe");
  oHiddFrame.onload = setPrint;
  oHiddFrame.style.visibility = "hidden";
  oHiddFrame.style.position = "fixed";
  oHiddFrame.style.right = "0";
  oHiddFrame.style.bottom = "0";
  oHiddFrame.src = sURL;
  document.body.appendChild(oHiddFrame);
}
</script>
</head>
<body>
  <p><span onclick="printPage('externalPage.html');" style="cursor:pointer;text-decoration:underline;color:#0000ff;">Print external page!</span></p>
</body>
</html>

第一次尝试:尝试在beforeContentPrint的ajax请求中放入asin:false,以便首先添加元素,然后调用打印。

var jqxhr = $.ajax({
   type: "GET",
   url: bookURL,
   async:false,
   success: function(data) {
     .....
     .....
     $(article).each(function () {
        parent.append(article);
     });
   },
   complete: function() {
     var timer = setInterval(function () {
        window.print();
     }, 900);
  }
 }

2ndAttempt:看看如何强制执行一个又一个函数。希望这能有所帮助。

由于添加的元素没有显示,因此很难确定确切的问题,但通过添加/插入文档来添加元素并不总是适用于所有浏览器,在最坏的情况下,您需要通过代码手动添加这些元素(document.createElement()appendChild()等)。

在尝试创建变通方案时,您可以尝试使用MutationObservers来跟踪文章元素的更改,这有望帮助您在DOM正确更新时触发打印。在新的浏览器中,这种支持相当不错(在某些浏览器中,您可能必须使用前缀,例如WebKitMutationObserver),而对于旧的浏览器,您可以提供回退-当然,这只会让您走到这一步。

这将监视目标元素的更改并触发回调。

基于本文的通用示例:

var article = document.querySelector('#articleID'),
    doPrint = false,    // must be available in global/parent scope
    o,
    useFallback = (typeof MutationObserver !== 'undefined');

if (!useFallback) {    
    o = new MutationObserver(function(mutations) {
        mutations.forEach(function(mutation) {
           // you can do additional filtering here
           // using the mutation object (.name, .type, ...)
           if (doPrint) {
               doPrint = false;
               window.print();
           }
       });
    });
    var cfg = { attributes: true, childList: true, characterData: true };
    o.observe(article, cfg);
}

现在观察者正在运行,您可以在成功回调中进行以下修改:

var timer;  // keep track of setTimeout so we can cancel it
success: function(data) {
   ...
   ...
$(article).each(function () {
    parent.append(article);
  });
  // after last element is added, add a "dummy" element
  doPrint = true;
  if (useFallback) {
     // fallback to setTimeout or other solution
  }
  else {
     parent.append('<br />');
  }
}

我在这里做了一个在线演示,它设置了观察者并添加了一些元素。打开控制台查看操作。该演示可能在数据方面过于有限,无法模拟您的情况,但对查看过程可能很有用。

这里用来触发打印对话框的机制本身可以讨论,如果是最好的——我只是为了举例而提供一个。

但您可以看到,当向article添加某些内容时,会触发观察者。这样您就知道DOM已经更新,并且应该可以进行打印。只有添加的最后一个元素才需要触发打印,因此才有doPrint标志。

如果您仍然没有成功,您将需要考虑以代码的方式手动添加元素,或者可能预定义一些在需要时注入的元素(如上所述,在不了解完整场景的情况下,必须进行猜测)。

它看起来像是setInterval,clearInterval把你搞砸了。更改为setTimeout并去掉afterprint函数中的clearInterval。我做了一把小提琴,可以在FF和IE9中使用。Fiddle

    complete: function() {
        var timer = setTimeout(function () {
        window.print();
      }, 900);
    }