我有这个功能来打印DIV
每当页面加载并点击我的“打印”链接时,显示DIV没有CSS打印。
如果我关闭Chrome的打印可视化页面并再次单击“打印”链接,则DIV已应用CSS。
任何想法为什么?
function printDiv(divId) {
var printDivCSSpre =
'<link href="/static/assets/vendor/sb-admin-2-1.0.7/bower_components/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">' +
'<link href="/static/assets/vendor/sb-admin-2-1.0.7/dist/css/sb-admin-2.css" rel="stylesheet">' +
'<div style="width:1000px; padding-right:20px;">';
var printDivCSSpost = '</div>';
$('body').append('<iframe id="print_frame" name="print_frame" width="0" height="0" frameborder="0" src="about:blank"></iframe>');
$("link").clone().appendTo($("#print_frame").contents().find("head"));
window.frames["print_frame"].document.body.innerHTML =
printDivCSSpre + document.getElementById(divId).innerHTML + printDivCSSpost;
window.frames["print_frame"].window.focus();
var windowInstance = window.frames["print_frame"].window;
windowInstance.print();
}
<a id="print" href="#">
<i class="fa fa-print"></i> Print
</a>
<script>
$('#print').click(function () {
printDiv('report')
})
</script>
<div id="report" class="report">
<p># Generated Table#</p>
</div>
答案 0 :(得分:3)
这是因为当您调用printDiv()函数时,css也是使用内部HTML编写的,在这种情况下,在第一次单击时不会应用CSS,因为即使在DIV中不存在CSS,也会向元素编写CSS。 / p>
根据需要工作的功能必须先写入DIV内容,然后再应用CSS。我会说在DIV的内容之后写css或者在HTML页面上加载,然后只写DIV内容。
希望有所帮助。
答案 1 :(得分:2)
正如其他人提到的,如果没有看到问题的工作示例很难看到你的问题,而只是从代码中猜测:
print()
来电之前加载CSS。print()
来电之前呈现CSS。记住改变你的JS功能可能会有所作为
function printDiv(divId) {
$("link").clone().appendTo($("#print_frame").contents().find("head"));
window.frames["print_frame"].document.body.innerHTML =
printDivCSSpre + document.getElementById(divId).innerHTML + printDivCSSpost;
window.frames["print_frame"].window.focus();
var windowInstance = window.frames["print_frame"].window;
setTimeout(function() {
windowInstance.print();
}, 0);
}
这个功能背后的想法是让浏览器在我们在窗口中添加更改HTML / CSS代码后执行它的代码 - 请参阅Why is setTimeout(fn, 0) sometimes useful?
警告:此方法未针对您的特定问题进行测试,也可能无效,因为我们转义/离开鼠标单击调用堆栈,调用print()
方法可能是不可能超出用户交互堆栈。
更新: - 我的假设是正确的,浏览器需要一些时间来加载和渲染CSS,这就是为什么在更改iframe后调用print()
的权利内容没有给出所需的结果。有3.5种方法可以解决这个问题:
iframe
元素及其子项的事件答案 2 :(得分:2)
试试这个。问题主要是因为在启动打印命令时css尚未应用于页面。 setTimeout
是其他人提到的解决问题的一种方法,但实际上无法预测您需要多少延迟。在触发print语句之前,缓慢的Internet连接需要很长的延迟。但是,以下代码仅在将css正确应用于iframe后触发打印事件。
$('#print').click(function () {
if($("#print_frame").length == 0) {
$('#report').after('<iframe id="print_frame" name="print_frame" width="0" height="0" frameborder="0" src="about:blank"></iframe>');
}
var $head = $("#print_frame").contents().find("head");
// for now for ease I will just empty head
// ideally you would want to check if this is not empty
// append css only if empty
$head.empty();
$.ajax({
url : "https://dl.dropboxusercontent.com/u/7760475/reports.css",
dataType: "text",
success : function (reports) {
// grab css and apply its content to the iframe document
$head.append('<style>'+reports+'</style>');
$.ajax({
url : "https://dl.dropboxusercontent.com/u/7760475/bootstrap.css",
dataType: "text",
success : function (bootstrap) {
// grab another css and apply its content to the iframe document
// there may be better ways to load both css files at once but this works fine too
$head.append('<style>'+bootstrap+'</style>');
// css has been applied
// clone your div and print
var $body = $("#print_frame").contents().find('body');
// empty for ease
// but later append content only if empty
$body.empty();
$("#report").clone().appendTo($body);
$('#print_frame').get(0).contentWindow.print();
}
});
}
});
});
答案 3 :(得分:1)
正如其他人所提到的,这里的问题是使用的CSS文件是外部资源,浏览器需要时间下载并在本地缓存。一旦它被缓存,它将更快地服务,这就是为什么它在第二次点击时工作正常。
正如Anton所说,setTimeout是关键所在!您可能会增加超时秒数以使其工作。我尝试将其设置为500毫秒,这很有效,
setTimeout(function(){windowInstance.print();},500);
答案 4 :(得分:1)
使用内联CSS代替。 原因:如果我们打印或保存为PDF,如果无法获取外部css文件,那么我们必须使用内联css。 编辑了您的文件,请参阅:jsfiddle.net/ytzcwykz/18 /
答案 5 :(得分:1)
每件事都是对的,只需改变顺序。在第一次单击的浏览器调试器中,它在源部分中没有显示'print_frame',而在第二次单击时它(我使用的是chrome devtool)。
因此在onload期间加载内存帧并使用css属性:
BC/OpenSSL
和onClick只需附加html
var windowInstance;
$(function(){
$('body').append('<iframe id="print_frame" name="print_frame" width="0" height="0" frameborder="0" src="about:blank"></iframe>');
$("link").clone().appendTo($("#print_frame").contents().find("head"));
windowInstance = window.frames["print_frame"].window;
});
更新jsfiddle