jquery - 在某些页面上的 IE 中拒绝 iframe 访问 [英] jquery - iframe access denied in IE on some pages

查看:15
本文介绍了jquery - 在某些页面上的 IE 中拒绝 iframe 访问的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是printThis的作者,一个用于打印的jquery插件.

I'm the author of printThis, a jquery plugin for printing.

https://github.com/jasonday/printThis

我有一个用户提出了一个问题,我无法破解,不幸的是,我无法分享页面(隐私问题).

I have a user that has brought up an issue, that I have been unable to crack and unfortunately, I am unable to share the page (privacy concerns).

在用户的站点上,该问题出现在 IE 中的某些页面上,而不是其他页面上.打印失败,因为 iframe 仍然是空的.

On the user's site, the issue presents on some pages in IE, but not others. The print is failing to happen, as the iframe remains empty.

IE 中的错误是在 jQuery 中:

The error in IE is within jQuery:

contents: function (a) {
            return f.nodeName(a,
                "iframe") ? a.contentDocument || a.contentWindow.document : f.makeArray(a.childNodes)
        }

使用日志记录,我能够确定它在这一行附近失败了:

Using logging, I was able to determine it was failing around this line:

var $doc = $("#" + strFrameName).contents();

但同样,这仅发生在某些页面上,我无法在该用户站点之外的任何实例中重新创建.

But again, this only happens on some pages and I have been unable to recreate in any instance outside of this user's site.

我的问题:这里有更好的方法吗?或使 $doc 对象更防弹的方法?

My question: Is there a better approach here? or a method to make the $doc object more bulletproof?

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

更新

问题是由于 document.domain

这种类型的页面设置了document.domain,IE 不会从父页面继承document.domain.

This type of page has document.domain set and IE does not inherit document.domain from the parent.

为了修复该部分,我将 iframe 创建更改为标准 javascript,并将源设置为在 iframe 创建时写入 document.domain.

To fix that portion, I changed the iframe creation to standard javascript and set the source to write document.domain on iframe creation.

    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);

所以这修复了拒绝访问的问题,但是现在框架不会打印.我尝试了很多不同的方法来访问该对象,但都没有奏效.

So this fixes the access denied, however now the frame won't print. I've tried a lot of different methods for accessing the object, however none of them are working.

A) 在这种情况下您将如何访问框架(我已经尝试了 SO 上概述的大多数方法)以使 IE 识别和打印

A) how would you access the frame in this scenario (i've tried most of the methods outlined on SO) to get IE to recognize and print

B) 谁能想出更好的方法在使用 jQuery 创建时将 document.domain 放入 iframe 中?(不能在之后,因为会出现访问被拒绝的问题)

B) can anyone think of a better way to get the document.domain into the iframe on creation with jQuery? (can't be afterwards, as the access denied issue will come up)

推荐答案

问题是由于 IE 没有继承父 document.domain.

Issue is due to IE not inheriting the parent document.domain.

不幸的是,一旦你进入这个阴暗的区域,就需要一些特定的技巧才能让它正常工作.

Unfortunately, once you get into this murky area, it took some specific hacks to get this to work properly.

基本上检查是否明确设置了 document.domain 并且浏览器是 IE.

Basically doing a check for if document.domain is being explicitly set and the browser is IE.

完整更新的插件:

https://github.com/jasonday/printThis

(function ($) {
    var opt;
    $.fn.printThis = function (options) {
        opt = $.extend({}, $.fn.printThis.defaults, options);
        var $element = this instanceof jQuery ? this : $(this);

            var strFrameName = "printThis-" + (new Date()).getTime();

            if(window.location.hostname !== document.domain && navigator.userAgent.match(/msie/i)){
                // Ugly IE hacks due to IE not inheriting document.domain from parent
                // checks if document.domain is set by comparing the host name against document.domain
                var iframeSrc = "javascript:document.write("<head><script>document.domain=\"" + document.domain + "\";</script></head><body></body>")";
                var printI= document.createElement('iframe');
                printI.name = "printIframe";
                printI.id = strFrameName;
                printI.className = "MSIE";
                document.body.appendChild(printI);
                printI.src = iframeSrc;

            } else {
                 // other browsers inherit document.domain, and IE works if document.domain is not explicitly set
                var $frame = $("<iframe id='" + strFrameName +"' name='printIframe' />");
                $frame.appendTo("body");
            }


            var $iframe = $("#" + strFrameName);

            // show frame if in debug mode
            if (!opt.debug) $iframe.css({
                position: "absolute",
                width: "0px",
                height: "0px",
                left: "-600px",
                top: "-600px"
            });


        // $iframe.ready() and $iframe.load were inconsistent between browsers    
        setTimeout ( function () {

            var $doc = $iframe.contents();

            // import page stylesheets
            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 title to iframe
            if (opt.pageTitle) $doc.find("head").append("<title>" + opt.pageTitle + "</title>");

            // import additional stylesheet
            if (opt.loadCSS) $doc.find("head").append("<link type='text/css' rel='stylesheet' href='" + opt.loadCSS + "'>");

            // grab $.selector as container
            if (opt.printContainer) $doc.find("body").append($element.outer());

            // otherwise just print interior elements of container
            else $element.each(function () {
                $doc.find("body").append($(this).html())
            });

            if($iframe.hasClass("MSIE")){
                // check if the iframe was created with the ugly hack
                // and perform another ugly hack out of neccessity
                window.frames["printIframe"].focus();
                setTimeout(function () {
                   $doc.find("head").append("<script>  window.print(); </script>");
                }, 500 );
            } else {
                // proper method
                $iframe[0].contentWindow.focus();
                $iframe[0].contentWindow.print();  
            }

             //remove iframe after print
            if (!opt.debug) {
                setTimeout(function () {
                    $iframe.remove();
                }, 1000);
            }


        }, 333 );

    };

    // defaults
    $.fn.printThis.defaults = {
        debug: false,           // show the iframe for debugging
        importCSS: true,        // import parent page css
        printContainer: true,   // print outer container/$.selector
        loadCSS: "",            // load an additional css file
        pageTitle: ""           // add title to print page
    };

    // $.selector container
    jQuery.fn.outer = function () {
        return $($("<div></div>").html(this.clone())).html()
    }
})(jQuery);

这篇关于jquery - 在某些页面上的 IE 中拒绝 iframe 访问的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆