te')); return $arr; } /* 遍历用户所有主题 * @param $uid 用户ID * @param int $page 页数 * @param int $pagesize 每页记录条数 * @param bool $desc 排序方式 TRUE降序 FALSE升序 * @param string $key 返回的数组用那一列的值作为 key * @param array $col 查询哪些列 */ function thread_tid_find_by_uid($uid, $page = 1, $pagesize = 1000, $desc = TRUE, $key = 'tid', $col = array()) { if (empty($uid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('uid' => $uid), array('tid' => $orderby), $page, $pagesize, $key, $col); return $arr; } // 遍历栏目下tid 支持数组 $fid = array(1,2,3) function thread_tid_find_by_fid($fid, $page = 1, $pagesize = 1000, $desc = TRUE) { if (empty($fid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('fid' => $fid), array('tid' => $orderby), $page, $pagesize, 'tid', array('tid', 'verify_date')); return $arr; } function thread_tid_delete($tid) { if (empty($tid)) return FALSE; $r = thread_tid__delete(array('tid' => $tid)); return $r; } function thread_tid_count() { $n = thread_tid__count(); return $n; } // 统计用户主题数 大数量下严谨使用非主键统计 function thread_uid_count($uid) { $n = thread_tid__count(array('uid' => $uid)); return $n; } // 统计栏目主题数 大数量下严谨使用非主键统计 function thread_fid_count($fid) { $n = thread_tid__count(array('fid' => $fid)); return $n; } ?>javascript - safari not allowing a second window.print() - Stack Overflow
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - safari not allowing a second window.print() - Stack Overflow

programmeradmin3浏览0评论

Hello I am running into a weird issue in Safari. I have a button and when clicked it prints the content of the html. My issue is that when calling on window.print() the first time it works great, however, on the second click it will display a popup stating:

'This webpage is trying to print. Do you want to print this webpage?'

If I click Print in this dialog nothing happens. Any ideas why this could be happening? Thank you in advance!

Javascript -

$scope.print = function() {
    var contents = document.getElementById("print-section").outerHTML;
    var frame1 = document.createElement('iframe');
    frame1.name = "frame3";
    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>'); // add some libraries for the new document
    frameDoc.document.write('</head><body>');
    frameDoc.document.write(contents);
    frameDoc.document.write('</body></html>');
    frameDoc.document.close();
    setTimeout(function () {
        window.frames["frame3"].focus();
        window.frames["frame3"].print();
        document.body.removeChild(frame1);
    }, 500);

    return false;
};

Html-

<div id="print-section">
   <div>Section to print<>
</div>

Hello I am running into a weird issue in Safari. I have a button and when clicked it prints the content of the html. My issue is that when calling on window.print() the first time it works great, however, on the second click it will display a popup stating:

'This webpage is trying to print. Do you want to print this webpage?'

If I click Print in this dialog nothing happens. Any ideas why this could be happening? Thank you in advance!

Javascript -

$scope.print = function() {
    var contents = document.getElementById("print-section").outerHTML;
    var frame1 = document.createElement('iframe');
    frame1.name = "frame3";
    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>'); // add some libraries for the new document
    frameDoc.document.write('</head><body>');
    frameDoc.document.write(contents);
    frameDoc.document.write('</body></html>');
    frameDoc.document.close();
    setTimeout(function () {
        window.frames["frame3"].focus();
        window.frames["frame3"].print();
        document.body.removeChild(frame1);
    }, 500);

    return false;
};

Html-

<div id="print-section">
   <div>Section to print<>
</div>
Share Improve this question edited Mar 11, 2019 at 20:43 Fedor 1,5783 gold badges29 silver badges39 bronze badges asked Jan 30, 2018 at 15:14 paul590paul590 1,4351 gold badge25 silver badges45 bronze badges 1
  • 1 Same problem here, any ideas? – Matteo Conta Commented Mar 14, 2018 at 15:06
Add a ment  | 

3 Answers 3

Reset to default 5

As Matteo Conta correctly mentioned, the problem is that Safari's print confirmation dialog does not stop JS code execution flow to wait for printing.
Therefore, what we really want is to detect when exactly does a print action end in order to run a cleanup absolutely safely.

setTimeout solution is a good starting point but I wanted to tackle the problem more reliably and have e up with an event-based solution using matchMedia and onfocus to catch the exact moment when printing is finished (either cancelled or pleted).

Below is the code that I've tested for this particular question (ES5, iframe printing).
Also, I've created a Gist on GitHub with a generic approach demonstrated. Hope it will be useful.

$scope.print = function () {
  var frame = appendFrame();

  // Safari
  if (!window.onafterprint) {
    // emulate onbeforeprint/onafterprint events
    var mediaQueryCallback = function (mql) {
      if (!mql.matches && frame) {
        document.body.removeChild(frame);
      }
    };
    var mediaQueryList = window.frames[frame.name].matchMedia('print');
    mediaQueryList.addListener(mediaQueryCallback);

    // the code below will trigger a cleanup in case a user hits Cancel button
    // in that Safari's new additional print confirmation dialog
    window.frames[frame.name].focus();
    window.frames[frame.name].onfocus = function () {
      return mediaQueryCallback(mediaQueryList);
    };
  }

  window.frames[frame.name].print();

  return false;
};

For brevity I've extracted the frame creation code into a trivial function (appendFrame) and omitted setTimeout call from the original question (after frameDoc.document.close(); line).

var appendFrame = function () {
  var contents = document.getElementById("print-section").outerHTML;
  var frame1 = document.createElement('iframe');
  frame1.name = "frame3";
  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>'); // add some libraries for the new document
  frameDoc.document.write('</head><body>');
  frameDoc.document.write(contents);
  frameDoc.document.write('</body></html>');
  frameDoc.document.close();

  return frame1;
};

inspired by MDN article:

onbeforeprint

After some investigation I found a solution.

Safari shows the print warning only if you "Cancel" the print. However the reason for the second blank print is that you remove too quickly the content using

document.body.removeChild(frame1)

If you increase the waiting time from 500ms to 5 secs you give the user the time to close the warning popup and print.

In my case I succesfully tested on Chrome/FF/Edge/Safari this jQuery plugin, increasing also in this library the removal timeout https://github./DoersGuild/jQuery.print

Adding onto this, using the jQuery Print plugin Matteo Conta mentions above, I was able to implement printing in Safari by doing a print in a new tab, no iframes, popup dialogue, blank prints, or delays.

The issue I was running into, as many people are and have been, was Safari having issues with subsequent prints within iframes, showing that print dialogue, and then a blank print.

Currently we use printThis JS as our printing plugin and had already implemented a 3000ms delay, but this new update Big Sur 14.1 specifically broke that implementation. jQuery Print plugin does not require any delays and may deprecate our use of printThis if we no longer e across anymore issues with Safari updates.

Note: Even with jQuery Print, if you choose to still print within an iframe you'll e across the same printing issues.

Below is a snippet of how I implemented the print based upon the user's browser. Hope this helps anyone still searching for a solution!

var currentBrowser;

// Determine user browser
if ( navigator.userAgent.indexOf("Chrome") != -1 ) {

  currentBrowser = "Google Chrome";

} else if ( navigator.userAgent.indexOf("Safari") != -1 ) {

  currentBrowser = "Safari";

} else {

  currentBrowser = "Others";
}

// Special Safari Treatment - Print New Window
if( currentBrowser === "Safari" ) {

  /**
   * jQuery Print JS
   *
   * Print receipts in new window with a deffered callback function.
   *
   * globalStyles - Will include style sheets from parent document
   * iframe - Print in a new window, iframe = false
   * deferred - Callback function 
   */
  $("#printDiv").print({
    globalStyles : true,
    iframe : false,
    deferred: $.Deferred().done(function() {

        // Callback
    })
  });

} else {

    // Print iframe normally using printThis JS
    $('#printDiv').printThis();
}
发布评论

评论列表(0)

  1. 暂无评论