Tôi là tác giả của printThis, một plugin jquery để in.jquery - truy cập iframe bị từ chối trong IE trên một số trang
https://github.com/jasonday/printThis
Tôi có một người sử dụng đã được đưa lên một vấn đề, mà tôi đã không thể để crack và không may, tôi không thể chia sẻ trang (mối quan tâm riêng tư).
Trên trang web của người dùng, sự cố hiển thị trên một số trang trong IE, nhưng không hiển thị trên các trang khác trong IE. Bản in sẽ không xảy ra vì khung nội tuyến vẫn trống.
Các lỗi trong IE là trong jQuery:
contents: function (a) {
return f.nodeName(a,
"iframe") ? a.contentDocument || a.contentWindow.document : f.makeArray(a.childNodes)
}
Sử dụng khai thác gỗ, tôi đã có thể xác định nó đã thất bại xung quanh dòng này:
var $doc = $("#" + strFrameName).contents();
Nhưng một lần nữa, điều này chỉ xảy ra trên một số trang và tôi không thể tạo lại trong bất kỳ trường hợp nào bên ngoài trang web của người dùng này.
Câu hỏi của tôi: Có cách tiếp cận nào tốt hơn ở đây không? hoặc một phương pháp để làm cho đối tượng $doc
chống đạn hơn?
// -----------------------------------------------------------------------
// printThis v1.1
// Printing plug-in for jQuery
//
// Resources (based on) :
// jPrintArea: http://plugins.jquery.com/project/jPrintArea
// jqPrint: https://github.com/permanenttourist/jquery.jqprint
// Ben Nadal: http://www.bennadel.com/blog/1591-Ask-Ben-Print-Part-Of-A-Web-Page-With-jQuery.htm
//
// Dual licensed under the MIT and GPL licenses:
// http://www.opensource.org/licenses/mit-license.php
// http://www.gnu.org/licenses/gpl.html
//
// (c) Jason Day 2012
//
// Usage:
//
// $("#mySelector").printThis({
// debug: false, //show the iframe for debugging
// importCSS: true, // import page CSS
// printContainer: true, // grab outer container as well as the contents of the selector
// loadCSS: "path/to/my.css" //path to additional css file
// });
//
// Notes:
// - the loadCSS option does not need @media print
//------------------------------------------------------------------------
(function($) {
var opt;
$.fn.printThis = function (options) {
opt = $.extend({}, $.fn.printThis.defaults, options);
var $element = (this instanceof jQuery) ? this : $(this);
// if Opera, open a new tab
if ($.browser.opera)
{
var tab = window.open("","Print Preview");
tab.document.open();
}
// add dynamic iframe to DOM
else
{
var strFrameName = ("printThis-" + (new Date()).getTime());
var $iframe = $("<iframe id='" + strFrameName +"' src='about:blank'/>");
if (!opt.debug) { $iframe.css({ position: "absolute", width: "0px", height: "0px", left: "-600px", top: "-600px" }); }
$iframe.appendTo("body");
}
// allow iframe to fully render before action
setTimeout (function() {
if ($.browser.opera)
{
var $doc = tab.document;
} else
{
var $doc = $("#" + strFrameName).contents();
}
// import page css
if (opt.importCSS)
{
$("link[rel=stylesheet]").each(function(){
var href = $(this).attr('href');
if(href){
var media = $(this).attr('media') || 'all';
$doc.find("head").append("<link type='text/css' rel='stylesheet' href='" + href + "' media='"+media+"'>");
}
});
}
// add another stylesheet
if (opt.loadCSS)
{
$doc.find("head").append("<link type='text/css' rel='stylesheet' href='" + opt.loadCSS + "'>");
}
//add title of the page
if (opt.titlePage)
{
$doc.find("head").append('<title>'+opt.titlePage+'</title>');
}
//grab outer container
if (opt.printContainer) { $doc.find("body").append($element.outer()); }
else { $element.each(function() { $doc.find("body").append($(this).html()); }); }
//$doc.close();
// print
($.browser.opera ? tab : $iframe[0].contentWindow).focus();
setTimeout(function() { ($.browser.opera ? tab : $iframe[0].contentWindow).print(); if (tab) { tab.close(); } }, 1000);
//removed iframe after 60 seconds
setTimeout(
function(){
$iframe.remove();
},
(60 * 1000)
);
}, 333);
}
$.fn.printThis.defaults = {
debug: false, //show the iframe for debugging
importCSS: true, // import page CSS
printContainer: true, // grab outer container as well as the contents of the selector
loadCSS: "", //path to additional css file
titlePage: "" //add title to print page
};
jQuery.fn.outer = function() {
return $($('<div></div>').html(this.clone())).html();
}
})(jQuery);
CẬP NHẬT
Issue để do document.domain
Đây là loại trang có document.domain
bộ và IE không kế thừa document.domain
từ cha mẹ.
Để sửa phần đó, tôi đã thay đổi việc tạo khung nội tuyến thành javascript chuẩn và đặt nguồn để viết document.domain
khi tạo khung nội tuyến.
var printI= document.createElement('iframe');
printI.name = "printIframe";
printI.id = strFrameName;
document.body.appendChild(printI);
printI.src = "javascript:document.write('<head><script>document.domain=\"mydomain.com\";</script></head><body></body>')";
var $iframe = $("#" + strFrameName);
Vì vậy, điều này sẽ khắc phục quyền truy cập bị từ chối, tuy nhiên khung này sẽ không in. Tôi đã thử rất nhiều phương pháp khác nhau để truy cập đối tượng, tuy nhiên không có phương pháp nào trong số chúng hoạt động.
A) làm thế nào bạn sẽ truy cập vào khung trong kịch bản này (Tôi đã thử hầu hết các phương pháp nêu trên SO) để có được IE để nhận ra và in
hoặc
B) bất cứ ai có thể nghĩ đến một cách tốt hơn để có được document.domain vào khung nội tuyến khi tạo bằng jQuery? (không thể sau đó, vì vấn đề truy cập bị từ chối sẽ xuất hiện)
Có phải tất cả các trang trong cùng một tên miền/tên miền phụ? – Christophe
@Christophe - vâng. Tất cả các trang đều nằm trong cùng một miền. Bản in không hoạt động cụ thể trên một loại trang, nhưng hoạt động trên tất cả các trang khác. – Jason
Có thể hữu ích: http://stackoverflow.com/questions/364952/jquery-javascript-accessing-contents-of-an-iframe – JSuar