另一个跨网域iframe调整Q& A的大小 [英] Yet Another cross-domain iframe resize Q&A

查看:574
本文介绍了另一个跨网域iframe调整Q& A的大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何调整来自其他网域的iframe



编辑



向下滚动一些解决方案..或阅读如何不这样做:D



经过许多小时的代码黑客 - 结论是,iframe中的任何东西都不是可访问,甚至在我的域上呈现的滚动条。



为了节省你的时间,甚至不要走这条路线,只需使用sendMessages进行跨域通信。
有HTML插件< 5,我使用 - 到底部一个很好的例子:)






过去几天我一直在试图集成iframe进入网站。这是一个短期解决方案,而另一方开发和API(可能需要几个月...)
因为这是短期解决方案,我们做了想使用easyXDM-我有访问其他域,但其困难足够要求他们添加p3p标头,因为它是.....



3 iframes



我发现的最接近的解决方案是3个iframe,但它的铬和safari的心理,所以我不能使用。



在chrome中打开





http://www.johnchapman.name/aspnet-proxy-page- cross-domain-requests-from-ajax-and-javascript /



重新呈现网页



我没有走这么远,但有一些jscript引擎,它会查看源代码,并根据源文件重新渲染页面。但是它需要黑客这些jscripts ..这不是一个理想的情况下商业实体...
和一些invole纯java小程序或服务器端渲染



http://en.wikipedia.org/wiki/Server-side_JavaScript



http://htmlunit.sourceforge.net/ < ; -java not jscript



http://maxq.tigris .org /






编辑09-2013
UPDATE / p>

这一切都可以用HTML5套接字做。但是easyXDM是非HTML5投诉页面的最佳选择。



解决方案1 ​​非常好的解决方案!



使用easyXDM



在您的服务器上,您以

 < html> 
< head>
< script src =scripts / easyXDM.jstype =text / javascript>< / script>
< script type =text / javascriptlanguage =javascript>

var transport = new easyXDM.Socket(/ **配置* / {
remote:http://www.OTHERDOMAIN.com/resize_intermediate.html?url=testpages/resized_iframe_1 .html,

//将内联框架附加到
的元素ID container:embedded,
onMessage:function(message,origin){
var settings = message.split(,);
//在母版页上使用jquery
//$('iframe').height(settings[0]);
//$('iframe').width(settings[1]);

//没有jquery的普通解决方案(如果不使用任何复杂页面)(默认)
this.container.getElementsByTagName (iframe)[0] .style.height = settings [0];
this.container.getElementsByTagName(iframe)[0] .style.width = settings [1];
}
});

< / script>

< / head>

< body>
< div id =embedded>< / div>
< / body>

,并且在调用者域中,他们只需要在同一个地方添加intermiedate_frame html和easyXDM.js 。



选项1



如果您不想向所有网页添加脚本,请查看选项2!



然后,他们可以只添加一个简单的jscript结束每个页面你需要调整大小才会发生。不需要在每个页面中包含easyxdm。

 < script type =text / javascript> 
window.onload = function(){parent.socket.postMessage((parseInt(document.body.clientHeight))+,+(document.body.clientWidth)); };
< / script>

我修改了它发送的参数。如果您希望宽度正常工作,则其他域上的页面需要在样式som中包含类似于以下内容的页面宽度:

 < style type =text / css> 
html,body {
overflow:hidden;
margin:0px;
padding:0px;
background-color:rgb(75,0,85);
color:white;
width:660px
}
a {
color:white;
访问:白色;
}
< / style>

这对我很有用。如果不包括宽度,框架表现有点奇怪,kind'of尝试猜测它应该是..,如果你需要它不会缩小。



< h2>选项2

修改中间框架以轮询变更



中间框架应该看起来像这样..

 <!doctype html> 
< html>
< head>

< title> Frame< / title>
< script type =text / javascriptsrc =easyXDM.js>
< / script>
< script type=text / javascript>
var iframe;
var socket = new easyXDM.Socket({
//这是一个后备 - 在许多情况下不需要
swf:easyxdm.swf,
onReady:function {
iframe = document.createElement(iframe);
iframe.frameBorder = 0;
document.body.appendChild(iframe);
iframe.src =THE HOST FRAME;
iframe.onchange = messageBack();

},
onMessage:function(url,origin){
iframe.src = url;
}
});

//探测child.frame的尺寸。
function messageBack(){
socket.postMessage(iframe.contentDocument.body.clientHeight +,+ iframe.contentDocument.body.clientWidth);
};

//轮询儿童每500ms的更改。
setInterval(messageBack(),500);

< / script>
< style type =text / css>
html,body {
overflow:hidden;
margin:0px;
padding:0px;
width:100%;
height:100%;
}

iframe {
width:100%;
height:100%;
border:0px;
}
< / style>
< /头>
< body>

< / body>
< / html>

如果大小有变化,可以使间隔对chaeck更有效,如果尺寸更改,的每500ms发布消息。如果实现此检查,那么您可以更改轮询低至50ms!有趣






跨浏览器工作速度快。伟大的调试功能!

  






解决方案2 工作但不是很好)



所以基本上如果你与其他域有共同协议,那么你可以添加一个库来处理sendmessage。如果你没有任何访问其他域..继续寻找更多的黑客 - 因为我找不到或完全证明这些我发现。



域将包含这些头部标记

 < script src =scripts / jquery-1.5.2.min.js type =text / javascript>< / script> 
< script src =scripts / jquery.postmessage.min.jstype =text / javascript>< / script>
< script src =scripts / club.jstype =text / javascript>< / script>

在club.js只是一些自定义调用我为调整大小调用, p>

  $(document).ready(function(){
var parent_url = decodeURIComponent(document.location.hash.replace / ^#/,'')),link;
//在每个url中添加源url哈希,以便在框架中导航时授权回调。无需点击任何链接就会中断通信,不会收到任何消息
$('a [href]')。each(function(){
this.href = this.href + document.location.hash;
});
//获取尺寸并发回调用页面
var h1 = document.body.scrollHeight;
var w1 = document.body.scrollWidth;
$ .postMessage({if_height:h1,if_width :w1},parent_url,parent);
});

你的页面将做所有的辛勤工作,并有一个不错的脚本...

  //这几乎像request.querystring用于获取iframe数据
function querySt(param,e){
gy = e.split(&);
for(i = 0; i ft = gy [i] .split(=);
if(ft [0] == param){
return ft [1];
}
}
}


$(function(){
//跟踪iframe维度
var if_height;
var if_width;
//以有意义的方式将父页面URL传递到Iframe(此URL可以是
//通过查询字符串传递或硬编码到子页面,这取决于你的需要)
src ='http://www.OTHERDOAMIN.co.uk/OTHERSTARTPAGE.htm'+'#'+ encodeURIComponent(document.location.href),
/ /将iframe附加到DOM中
iframe = $('< iframesrc ='+ src +'width =100%height =100%scrolling =noframeborder = 0>< \ / iframe>')appendTo('#iframe');

//设置一个回调来处理已发送的MessageEvent事件在
/ / window.postMessage支持,传递的事件将有.data,.origin和
// .source属性,否则只有.data属性。
$ .receiveMessage(function(e){
//从传递的数据中获取高度
// var h = Number(e.data.replace(/.* if_height = \d +)(?:& | $)/,'$ 1'));
var h = querySt(if_height,e.data);
var w = querySt(if_width ,e.data);


if(!isNaN(h)& h> 0&& h!== if_height){
//高度已更改,更新iframe。
iframe.height(if_height = h);
}
if(!isNaN(w)&& w> 0&& w !== if_width){
//高度已更改,更新iframe
iframe.width(if_width = w);
}
//仅用于调试如果你想要
$('body')prepend(Recieved+ h +hX+ w +w ..);
//可选的原始URL忽略其中window.postMessage不受支持)。
//这里必须输入其他domain.com名称!这就像一个身份验证,以防止欺骗和xss攻击!
},'http://www.OTHERDOMAIN.co.uk');
});






选项3



他们现在是一个小JS库,用于管理调整跨域iFrames的大小,它仍然需要iFrame有一点JavaScript在其中,然而,这只是2.8k(765字节Gzipped)的原生JS没有任何依赖性,它不做任何事情,直到父页面调用。这意味着它是一个很好的客人在其他人的系统。



此代码使用mutationObserver检测DOM更改,并查找调整大小事件,以便iFrame保持与内容大小一致。适用于IE8 +。



https:// github .com / davidjbradshaw / iframe-resizer

解决方案

事情是 - 因为您需要获取从一个域中的文档到另一个域中的文档的计算出的高度。



因此,您可以使用 postMessage (适用于所有适用的浏览器),或者您花费5分钟调整 resize iframe example from easyXDM。



另一方只需要将几个文件复制到自己的域中,并在其文档中添加一行代码。


How do i resize an iframe from another domain

-Edit

Scroll down for some solutions.. or read on how NOT to do this :D

After many hours of code hacking- the conclusion is that anything inside the iframe is not accessible, even the scrollbars that render on my domain. I have tried many techniques to no avail.

To save you time dont even go down this route just use sendMessages for cross domain communications. There are plug ins for HTML < 5 that i use- Go to the bottom for a nice example :)


Past few days I have been trying to integrate an iframe into a site. This is a short term solution while the other side develops and API(could take months...) And because this is as short term solution we done want to use easyXDM- I have access to the other domain but its difficult enough asking them to add p3p header as it is.....

3 iframes

The closest solution I found was the 3 iframes- but it goes mental of chrome and safari so i cannot use that.

open in chrome

http://css-tricks.com/examples/iFrameResize/crossdomain.php#frameId=frame-one&height=1179

Measure the scrollbars

I found a another post on how to use the scrollheight to try and resize the form.. in theory it works well but I could not apply it properly using the iframes scroll height..

document.body.scrollHeight

That obvoisly uses the bodies height (cannot access these properties 100% is based on the clients display canvaz and not the x-domains document height)

i tired using jquery to get the iframes height

$('#frameId').Height()

$('#frameId').clientHeight

$('#frameId').scrollHeight

return values different in chrome and ie - or just don't make sense at all. The problem is that everything inside the frame is denied- even the scrollbar...

Computed Styles

But if I inspect and element in chrome of the iframe it bladdy shows me the documents dimensions inside the iframe (using jquery x-domain to get iframe.heigh - access denied) There is nothing in the computed CSS

Now how does chrome calculate that? (edit- browser re-renders the page using its build in rendering engine to calcualte all these settings - but are not attached anywhere to prevent cross-domain fraud.. so..)

HTML4

I read specification of HTML4.x and it says there that there should be read-only values exposed via document.element but its access denied via jquery

Proxy Frame

I went down the route of proxying the site back and calculating which is OK.. until a user logs in through the iframe and the proxy gets a login page instead of the actual content. Also to some calling the page twice is not acceptable

http://www.codeproject.com/KB/aspnet/asproxy.aspx

http://www.johnchapman.name/aspnet-proxy-page-cross-domain-requests-from-ajax-and-javascript/

Re-Render the page

I did not go this far but there are jscript engines out there that will look at the source and re-render the page based on the source file . but it would require hacking those jscripts.. and thats not an ideal situation for commercial entities... and some invole pure java applets or server side rendering

http://en.wikipedia.org/wiki/Server-side_JavaScript

http://htmlunit.sourceforge.net/ <-java not jscript

http://maxq.tigris.org/


EDIT 09-2013 UPDATE

All this can do done with HTML5 sockets. But easyXDM is great fallback for non HTML5 complaint pages.

Solution 1 Very Great Solution!

Using easyXDM

On your server you set up a page in the form of

<html>
<head>
<script src="scripts/easyXDM.js" type="text/javascript"></script>
<script type="text/javascript" language="javascript">

    var transport = new easyXDM.Socket(/** The configuration */{
    remote: "http://www.OTHERDOMAIN.com/resize_intermediate.html?url=testpages/resized_iframe_1.html",

    //ID of the element to attach the inline frame to
    container: "embedded",
    onMessage: function (message, origin) {
        var settings = message.split(",");
        //Use jquery on a masterpage.
        //$('iframe').height(settings[0]);
        //$('iframe').width(settings[1]);

        //The normal solution without jquery if not using any complex pages (default)
        this.container.getElementsByTagName("iframe")[0].style.height = settings[0];
        this.container.getElementsByTagName("iframe")[0].style.width = settings[1];
    }
});

</script>

</head>

<body>
    <div id="embedded"></div>
</body>

and on the callers domain they just need to add the intermiedate_frame html and easyXDM.js in the same place. Like a parent folder - then you can access relative directories or a contained folder just for you.

OPTION 1

If you don't want to add scripts to all pages look at option 2!

Then they can just add a simple jscript to the end of each the pages you need the resize to occur. No need to include the easyxdm in each of these pages.

 <script type="text/javascript">
            window.onload = function(){ parent.socket.postMessage( (parseInt(document.body.clientHeight)) + "," + ( document.body.clientWidth ) );  };
        </script>

I have modified the parameters it sends. If you want the width to work properly then the pages on the otherdomain need to include the width of the page in a style somwhere that look something similar to:

<style type="text/css">
            html, body {
                overflow: hidden;
                margin: 0px;
                padding: 0px;
                background-color: rgb(75,0,85);
                color:white;
                width:660px
            }
            a {
            color:white;
            visited:white;
            }
        </style>

This works great for me. If the width is not included then the frame behaves a bit strange and kind'of tries to guess what it should be .. and will not shrink down if you need it to.

OPTION 2

Modify the intermediate frame to poll for changes

Your intermediate frame should look something like this..

    <!doctype html>
<html>
    <head>

        <title>Frame</title>
        <script type="text/javascript" src="easyXDM.js">
        </script>
        <script type="text/javascript">
            var iframe;
            var socket = new easyXDM.Socket({
                //This is a fallback- not needed in many cases
                swf: "easyxdm.swf",
                onReady: function(){
                    iframe = document.createElement("iframe");
                    iframe.frameBorder = 0;
                    document.body.appendChild(iframe);
                    iframe.src = "THE HOST FRAME";
            iframe.onchange = messageBack();

                },
                onMessage: function(url, origin){
                    iframe.src = url;
                }
            });

            //Probe child.frame for dimensions.
            function messageBack(){
                socket.postMessage ( iframe.contentDocument.body.clientHeight + "," + iframe.contentDocument.body.clientWidth); 
            };

            //Poll for changes on children every 500ms.
            setInterval("messageBack()",500); 

        </script>
        <style type="text/css">
            html, body {
                overflow: hidden;
                margin: 0px;
                padding: 0px;
                width: 100%;
                height: 100%;
            }

            iframe {
                width: 100%;
                height: 100%;
                border: 0px;
            }
        </style>
    </head>
    <body>

    </body>
</html>

The interval could be made more efficient to chaeck if size has change and only send if the dimensions changes isntead of posting messaging every 500ms. If you implement this check then you can change the polling as low as 50ms! have fun


Work across browsers and is fast. Great debugging features !!

Excellent Work to  Sean Kinsey  who made the script!!!


Solution 2 (Works but not great)

So basically if you have a mutual agreement with the other domain then you can add a library to handle sendmessage. If you do not have any access the the other domain.. Keep on looking for more hacks- because I could not find or fully justify these I found.

So the other domain will include these in there Head tag

<script src="scripts/jquery-1.5.2.min.js" type="text/javascript"></script>
<script src="scripts/jquery.postmessage.min.js" type="text/javascript"></script>
<script src="scripts/club.js" type="text/javascript"></script>

In the club.js is just some custom calls i made for resize calls and contains..

 $(document).ready(function () {   
    var parent_url = decodeURIComponent( document.location.hash.replace( /^#/, '' ) ),link;
//Add source url hash to each url to authorise callback when navigating inside the frame.Without this clicking any links will break the communication and no messages will be received
$('a[href]').each(function(){ 
     this.href = this.href + document.location.hash ;
});
//Get the dimensions and send back to calling page.
var h1 = document.body.scrollHeight;
var w1 = document.body.scrollWidth;
$.postMessage({ if_height: h1, if_width: w1 }, parent_url, parent );
  });

And your page will do all the hard work and has a nice script...

  //This is almost like request.querystring used to get the iframe data
  function querySt(param, e) {
         gy = e.split("&");
         for (i = 0; i < gy.length; i++) {
             ft = gy[i].split("=");
             if (ft[0] == param) {
                 return ft[1];
             }
         }
     }


     $(function () {
         // Keep track of the iframe dimensions.
         var if_height;
         var if_width;
         // Pass the parent page URL into the Iframe in a meaningful way (this URL could be
         // passed via query string or hard coded into the child page, it depends on your needs).
         src = 'http://www.OTHERDOAMIN.co.uk/OTHERSTARTPAGE.htm' + '#' + encodeURIComponent(document.location.href),
         // Append the Iframe into the DOM.
         iframe = $('<iframe " src="' + src + '" width="100%" height="100%" scrolling="no" frameborder="0"><\/iframe>').appendTo('#iframe');

         // Setup a callback to handle the dispatched MessageEvent event. In cases where
         // window.postMessage is supported, the passed event will have .data, .origin and
         // .source properties. Otherwise, this will only have the .data property.
         $.receiveMessage(function (e) {
             // Get the height from the passsed data.
             //var h = Number(e.data.replace(/.*if_height=(\d+)(?:&|$)/, '$1'));
             var h = querySt("if_height", e.data);
             var w = querySt("if_width", e.data);


             if (!isNaN(h) && h > 0 && h !== if_height) {
                 // Height has changed, update the iframe.
                 iframe.height(if_height = h);
             }
             if (!isNaN(w) && w > 0 && w !== if_width) {
                 // Height has changed, update the iframe.
                 iframe.width(if_width = w);
             }
             //For debugging only really- can remove the next line if you want
             $('body').prepend("Recieved" + h + "hX" + w + "w .. ");
             // An optional origin URL (Ignored where window.postMessage is unsupported).
           //Here you must put the other domain.com name only! This is like an authentication to prevent spoofing and xss attacks! 
         }, 'http://www.OTHERDOMAIN.co.uk');
     });


OPTION 3

Their is now a small JS library for managing resizing cross-domain iFrames, it still requires the iFrame to have a bit of JavaScript in it, however, this is just 2.8k (765 bytes Gzipped) of native JS that does not have any dependancies and it doesn't do anything until called by the parent page. This means it's a nice guest on other people systems.

This code uses mutationObserver to detect DOM changes and also looks out for resize events, so that the iFrame remains sized to the content. Works in IE8+.

https://github.com/davidjbradshaw/iframe-resizer

解决方案

The thing is - there is no other way than using Cross-Domain Messaging for this since you need to get the computed height from a document in one domain, to a document in a different domain.

So, either you do this using postMessage (works in all moder browsers), or you spend 5 minutes adapting the resize iframe example from easyXDM.

The other party really just needs to copy a few files onto their domain, and add a single line of code to their document..

这篇关于另一个跨网域iframe调整Q&amp; A的大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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