新添加的HTML上的Javascript window.print()问题

时间:2013-08-29 16:59:13

标签: javascript jquery html ajax printing

问题是新内容不会打印(更多元素)。

当用户点击我的打印链接时,我会在调用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中使用此逻辑正常工作。

4 个答案:

答案 0 :(得分:1)

我不知道为什么会这样,但有一个解决方案在mozilla docs;打印隐藏的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>

答案 1 :(得分:1)

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

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:看看Here如何强制执行一个又一个的功能。 希望这会有所帮助。

答案 2 :(得分:0)

看起来像setInterval,clearInterval正在弄乱你。更改为setTimeout并删除afterprint函数中的clearInterval。我制作了一个适用于FF和IE9的小提琴。 Fiddle

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

答案 3 :(得分:0)

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

尝试创建解决方法时,您可以尝试使用MutationObservers来跟踪文章元素的更改,这有助于在DOM正确更新时帮助您触发打印。在新浏览器中支持相当不错(你可能不得不在某些地方使用前缀,例如WebKitMutationObserver),对于旧浏览器,你可以提供后备 - 当然这只能让你到目前为止。

这将监视目标元素的变化并触发回调。

基于this article的通用示例:

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 />');
  }

}

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

如果最好的话,可以讨论这里用于触发打印对话框本身的机制 - 我只是提供一个例子。

但是你可以看到在article添加某些内容时会触发观察者。这样您就知道DOM已经更新,它应该可用于打印。只有最后添加的元素需要触发打印,因此doPrint标志。

如果您仍然没有成功,您将需要考虑以代码方式手动添加元素,或者可能预定义您在需要时注入的一些元素(如上所述,不知道这里的完整场景,它必须与猜测一致)。