在YUI3下打印Panel内容
最近在用YUI3.5制作一个报表网站,遇到个问题,需要打印报表,但是YUI下我是通过model化panel来显示报表内容的,一打印就把整个网页打出来,结果是背景完全是乱的,样式也不正常
YUI3的panel也是通过div实现的,于是想是否能通过只打印div内容方式实现
在网上搜索了下,打印div本身还是比较容易的,代码是这样的:
<script language="javascript"> function printdiv(printpage) { var headstr = "<html><head><title></title></head><body>"; var footstr = "</body>"; var newstr = document.all.item(printpage).innerHTML; var oldstr = document.body.innerHTML; document.body.innerHTML = headstr+newstr+footstr; window.print(); document.body.innerHTML = oldstr; return false; } </script>
好吧,看起来很简单,其实就是把当前网页的innerHTML设置成div的内容,打印完后再设置回去
试了下,document.all.item有点问题,改成
<script language="javascript"> function printdiv(printpage) { var headstr = "<html><head><title></title></head><body>"; var footstr = "</body>"; var newstr = document.getElementById(printpage).innerHTML; var oldstr = document.body.innerHTML; document.body.innerHTML = headstr+newstr+footstr; window.print(); document.body.innerHTML = oldstr; return false; } </script>
打印是成功了,但是YUI3下这个代码是有着严重问题的:
网页所有的YUI代理、事件什么的在页面打印完恢复后全部被破坏了,执行完后,panel的关闭按钮,panel上的按钮什么的所有操作都完蛋了,也就是说,恢复后只剩了个页面的壳了
于是想新的办法处理,就是弹出一个新的窗口,然后把内容设置到新窗口打印完后关闭
代码是这样的
printdiv: function(e, printpage) { var headstr = '<html><head></head><body>'; var footstr = "</body>"; var contentstr = document.getElementById(printpage).innerHTML;
var openwindow = window.open('', 'newwindow', 'height=100, width=100, top=0, left=0,toolbar=no, menubar=no, scrollbars=no, resizable=no, location=no, status=no') openwindow.document.body.innerHTML = contentstr;
openwindow.print(); openwindow.close(); }
结果是打印出来了,但是打印出来的样式完全不正确
试了几种方法,最后确认以上代码有几点问题:
1、据说最好不要使用document.body.innerHTML,这个东西不是所有浏览器都支持
2、怎么设置innerHTML都不行,无法实现样式,最后是通过document.write方法才能实现
3、head里需要设置和要打印页面一样的css才行
4、document.write后面需要跟document.close来关闭输出流,一开始没写这个,导致页面打印不出来(但是刷新这个新页面,然后就会弹出打印对话框了)
最后的代码是这样的:
printdiv: function(e, printpage) { var headstr = '<html><head><title></title><link rel="stylesheet" href="../YUI3/cssreset/cssreset.css" type="text/css" /><link rel="stylesheet" href="../YUI3/cssfonts/cssfonts.css" type="text/css" /><link rel="stylesheet" href="../YUI3/cssgrids/cssgrids.css" type="text/css" /><link rel="stylesheet" href="../config/project.css" type="text/css" /></head><body id="doc" class="yui3-skin-sam">'; var footstr = "</body></html>"; var contentstr = document.getElementById(printpage).innerHTML; var openwindow = window.open('', 'newwindow', 'height=100, width=100, top=0, left=0,toolbar=no, menubar=no, scrollbars=no, resizable=no, location=no, status=no') openwindow.document.write(headstr + contentstr + footstr); openwindow.document.close(); openwindow.print(); openwindow.close(); }
然后外面调用的方法是:
Y.one('#v2012-print').on('click', Y.ActionHandler.printdiv, Y.one('#v2012-print'), 'v2012-content');
我这里是把printdiv放到了ActionHandler模块里,传递事件时需要额外的参数,第三个参数是事件对象本身,第四个参数是打印的div名称
最后要说的是,这个打印div最后还是有以下两点问题:
1、因为只打印div,当此div有由父级继承或通过对象层次实现的CSS时,此CSS在新窗口是无效的,如果想生效,必须在外层进行CSS包装
2、如果div里有ActiveX控件,ActiveX控件的展现内容是无法保持和原本div里的展现相同的,这个要解决的话必须自行通过ActiveX控件实现数据或图像复制