蓝森林首页 | 返回主页 | 本站地图 | 站内搜索 | 联系信箱 |
 您目前的位置:首页 > 自由软件 > 技术交流 > 应用编程


    

蓝森林 http://www.lslnet.com 2006年8月25日 8:28

JS跨域取得iFrame.scrollHeight的困境.

以下自适应iFrame高度的代码(多谢无名作者)在同域访问时没有问题;
但由于某种原因,我需要在网页内嵌入不同域名的框架(用代理商的域名给每个代理商一个首页,头尾是该代理商的信息;中间是我们网站的首页 - - iFrame与引用它的页面在同一台服务器上,但域名不同 - - 需要根据页面跳转自适应高度 - - 瞧,我并不是想作小偷,呵呵),上网一查方知 - - 这竟是一个尚未解决的大难题...
不知道经典的高手们有没有兴趣试一试?如能找到一个变通的办法(譬如在被引用的页面内加入代码,向引用它的页面传递scrollHeight数值?),hutuu不胜感激!

[html]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<meta content="all" name="robots" />
title>...</title>
<style type="text/css">
.abc_01a{
        color: #FFFFFF;
        text-decoration: none;
        float: left;
        background-color: #849452;
}
-->
</style>
</head>
<script language="JavaScript">
//** iframe自动适应页面 **//

//输入你希望根据页面高度自动调整高度的iframe的名称的列表:
//用逗号把每个iframe的ID分隔. 例如: ["myframe1", "myframe2"],可以只有一个窗体,则不用逗号。

//定义iframe的ID
var iframeids=["dealer"]

//如果用户的浏览器不支持iframe是否将iframe隐藏 yes 表示隐藏,no表示不隐藏
var iframehide="yes"

function dyniframesize()
{
var dyniframe=new Array()
for (i=0; i<iframeids.length; i++)
{
if (document.getElementById)
{
//自动调整iframe高度
dyniframe[dyniframe.length] = document.getElementById(iframeids[i]);
if (dyniframe[i] && !window.opera)
{
dyniframe[i].style.display="block"
if (dyniframe[i].contentDocument && dyniframe[i].contentDocument.body.offsetHeight) //如果用户的浏览器是NetScape
dyniframe[i].height = dyniframe[i].contentDocument.body.offsetHeight;
else if (dyniframe[i].Document && dyniframe[i].Document.body.scrollHeight) //如果用户的浏览器是IE
dyniframe[i].height = dyniframe[i].Document.body.scrollHeight;
}
}
//根据设定的参数来处理不支持iframe的浏览器的显示问题
if ((document.all || document.getElementById) && iframehide=="no")
{
var tempobj=document.all? document.all[iframeids[i]] : document.getElementById(iframeids[i])
tempobj.style.display="block"
}
}
}

if (window.addEventListener)
window.addEventListener("load", dyniframesize, false)
else if (window.attachEvent)
window.attachEvent("onload", dyniframesize)
else
window.onload=dyniframesize
</script>
<body>
<table width="788" height="100%" border="0" cellpadding="0" cellspacing="0">
    <tr>
      <td valign="top" class="abc_01a">....</td>
    </tr>
        <tr>
    <td valign="top"><iframe id="dealer" onload="javascript:{dyniframesize('dealer');}"
width="791" height="680" name="dealer" border="0" marginwidth="0" marginheight="0" src="http://www.blueidea.com" noresize frameborder="no" scrolling="no"></iframe></td>
  </tr>   
</table>
</body>
</html>
[/html]

上面是同一域名的,自适应高度代码管用.

这是不同域名的例子,提示错误是:没有权限.

[html]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<meta content="all" name="robots" />
<title>........</title>
<style type="text/css">
.abc_01a{
        color: #FFFFFF;
        text-decoration: none;
        float: left;
        background-color: #ffaa16;
}
-->
</style>
</head>
<script language="JavaScript">
//** iframe自动适应页面 **//

//输入你希望根据页面高度自动调整高度的iframe的名称的列表:
//用逗号把每个iframe的ID分隔. 例如: ["myframe1", "myframe2"],可以只有一个窗体,则不用逗号。

//定义iframe的ID
var iframeids=["dealer"]

//如果用户的浏览器不支持iframe是否将iframe隐藏 yes 表示隐藏,no表示不隐藏
var iframehide="yes"

function dyniframesize()
{
var dyniframe=new Array()
for (i=0; i<iframeids.length; i++)
{
if (document.getElementById)
{
//自动调整iframe高度
dyniframe[dyniframe.length] = document.getElementById(iframeids[i]);
if (dyniframe[i] && !window.opera)
{
dyniframe[i].style.display="block"
if (dyniframe[i].contentDocument && dyniframe[i].contentDocument.body.offsetHeight) //如果用户的浏览器是NetScape
dyniframe[i].height = dyniframe[i].contentDocument.body.offsetHeight;
else if (dyniframe[i].Document && dyniframe[i].Document.body.scrollHeight) //如果用户的浏览器是IE
dyniframe[i].height = dyniframe[i].Document.body.scrollHeight;
}
}
//根据设定的参数来处理不支持iframe的浏览器的显示问题
if ((document.all || document.getElementById) && iframehide=="no")
{
var tempobj=document.all? document.all[iframeids[i]] : document.getElementById(iframeids[i])
tempobj.style.display="block"
}
}
}

if (window.addEventListener)
window.addEventListener("load", dyniframesize, false)
else if (window.attachEvent)
window.attachEvent("onload", dyniframesize)
else
window.onload=dyniframesize
</script>
<body>
<table width="788" height="100%" border="0" cellpadding="0" cellspacing="0">
    <tr>
      <td valign="top" class="abc_01a">....</td>
    </tr>
        <tr>
    <td valign="top"><iframe id="dealer" onload="javascript:{dyniframesize('dealer');}"
width="791" height="680" name="dealer" border="0" marginwidth="0" marginheight="0" src="http://pages.blueidea.com/" noresize frameborder="no" scrolling="no"></iframe></td>
  </tr>   
</table>
</body>
</html>
[/html]

你说的这种情况不难解决,就像你说的:找到一个变通的办法(譬如在被引用的页面内加入代码,向引用它的页面传递scrollHeight数值)

window.name 应该是可以跨域访问的(我没法测试,这是根据俺的经验说的,有问题请继续问)。

那么被包含的页 [code]onload="window.name=window.document.body.scrollHeight;"[/code]

主页面[code] onload="document.getElementById('iframeID').style.height=window.frames[frameIndex].name;"[/code]
ps: 注意这里对 iframe 引用方式的不同之处

未测试,有问题请继续

多谢聱牙版主热心回应.
真不好意思,我只是美工:P,不懂程序 - - 不过,您让我问我就硬着脑袋问啦....

您的意思是说其它语句都不需要,只需要在内置入iFrame的站内body内加入onload="window.name=window.document.body.scrollHeight;"

引用iFrame页的iFrame处,
写onload="document.getElementById('iframeID').style.height=window.frames[frameIndex].name;"就可以了吗?
[frameIndex]需要特别定义吗?如何定义呢?

我做了一个测试,没起作用.一定是我把您的意思弄错了:
http://dealer.italkbb.com/iframe_test.asp

麻烦您再帮忙看一下.谢谢...谢谢..:)

俺的 frameIndex 意思是 iframe 的顺序号,就是说,如果你那页只有一个 iframe,那么就应该是
onload="document.getElementById('iframeID').style.height=window.frames[0].name;"

[b][color=#FF0000]不过俺刚才试了一下,发现 window.name 也不能跨域访问[/color][/b]


所以俺决定换个方法,用剪贴板来传数据,缺点是 IE Only


那么被包含的页 [code]onload="window.clipboardData.setData('text',window.document.body.scrollHeight);"[/code]


主页面 [code]onload="document.getElementById('iframeID').style.height=window.clipboardData.getData('text');"[/code]


呀!有90%的胜率也不错呀!呵呵,聱牙版主的头脑真是太灵活了,:)

可惜我到底没能领会:
http://dealer.italkbb.com/iframe_test.asp - - 不管是加在Body还是iFrame里页面都是提示"参数无效",一定有哪里被我弄错了.抱歉呐,还要劳你费心瞧瞧:)

Sorry 因为没有办法详细测试所以 bug 在所难免.....呵呵

那么被包含的页 [code]onload="window.clipboardData.setData('text',String(window.document.body.scrollHeight));"[/code]


主页面 [code]onload="document.getElementById('iframeID').style.height=parseInt(window.clipboardData.getData('text'))+'px';"[/code]

谢谢你呀,聱牙版主,你的代码很好用:)

呵呵,不知道我是不是太贪心 - - 尚有个不情之请 - - 现在:
http://dealer.italkbb.com/iframe_test.asp 取得iFrame.scrollHeight的代码只在第一次加载的时候有用(我已在所有2级的header.inc里也加了onload...我原本希望,它可以在被引用的站内跳转页面时自动适应高度的 - - 1楼的代码能做到哟),不知道,有没有办法让iFrame页面跳转时自动刷新一下记事本(cookie)的scrollHeight呢?

贪得无厌的人真讨厌,对吧,呵呵:))

不算贪得无厌啦,呵呵,是俺考虑不周

那么代码就会变的复杂些

那么被包含的页 [code]onload="window.clipboardData.setData('text',String('frameHeight='+window.document.body.scrollHeight));"[/code]


主页面 [code]
<script>
function resetIframeHeight(){
try{
  var str=window.clipboardData.getData('text');
  var obj=document.getElementById('iframeID');
  if(str.match(/^frameHeight=\d+$/)){
    obj.style.height=parseInt(str)+'px';
    window.clipboardData.setData('text','null');
  }
}catch(e){}
setTimeout(resetIframeHeight,300);
}
</script>
<body onload="resetIframeHeight();">
[/code]

聱牙版主:我照着新样子把衣裳裁了.却意外地发现它变得不能穿.您再搭把剪子吧:)

PS:(/^frameHeight=\d+$/)似乎少了一个"I"?
300豪秒以后发生了什么事情?如果页面所在的服务器反应比较慢或者状态时好时坏,会不会导致来不及取得剪贴板上的数据就清零了呢?

外行不会提问,聱牙版主请多包涵:)

依旧是一点小 bug。。。。这次俺本地测试过了.....应该不会有问题了吧.....

既然你担心300毫秒太长,俺就改成100毫秒了.....应该不会出现你担心的情况

主页面 [code]
<script>
function resetIframeHeight(){
try{
  var str=window.clipboardData.getData('text');
  var obj=document.getElementById('iframeID');
  if(str.match(/^frameHeight=\d+$/)){
    obj.style.height=parseInt(str.match(/\d+/))+'px';
    window.clipboardData.setData('text','null');
  }
}catch(e){}
setTimeout(resetIframeHeight,100);
}
</script>
<body onload="resetIframeHeight();">
[/code]


呵呵,新衣裳没问题了.聱牙版主:记着我欠你一个人情:)

聱牙版主,再打搅一下:这篇文章对剩下的10%会不会有用呢?

出处:
http://www.krikkit.net/howto_javascript_copy_clipboard.html

[color=gray]
copy text to clipboard with javascript        
Friday, 28 October 2005  
a very popular article about how to copy text to clipboard out of HTML with javascript in firefox/mozilla/netscape and IE
this is a javascript that i built out of several sources so that it is possible to copy text out of HTML in firefox/mozilla/netscape and in Internet Explorer

large parts of that script are copied from other sources, thats why there are dutch comments ;-)

this script only works in mozilla if you sign the javascript or if you change some settings in firefox... see notes below...
[/color]
[code]
<script language="javascript" type="text/javascript">
<!--
function copy_clip(meintext)
{
if (window.clipboardData)
   {
   
   // the IE-manier
   window.clipboardData.setData("Text", meintext);
   
   // waarschijnlijk niet de beste manier om Moz/NS te detecteren;
   // het is mij echter onbekend vanaf welke versie dit precies werkt:
   }
   else if (window.netscape)
   {
   
   // dit is belangrijk maar staat nergens duidelijk vermeld:
   // you have to sign the code to enable this, or see notes below
   netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
   
   // maak een interface naar het clipboard
   var clip = Components.classes['@mozilla.org/widget/clipboard;1']
                 .createInstance(Components.interfaces.nsIClipboard);
   if (!clip) return;
   
   // maak een transferable
   var trans = Components.classes['@mozilla.org/widget/transferable;1']
                  .createInstance(Components.interfaces.nsITransferable);
   if (!trans) return;
   
   // specificeer wat voor soort data we op willen halen; text in dit geval
   trans.addDataFlavor('text/unicode');
   
   // om de data uit de transferable te halen hebben we 2 nieuwe objecten
   // nodig om het in op te slaan
   var str = new Object();
   var len = new Object();
   
   var str = Components.classes["@mozilla.org/supports-string;1"]
                .createInstance(Components.interfaces.nsISupportsString);
   
   var copytext=meintext;
   
   str.data=copytext;
   
   trans.setTransferData("text/unicode",str,copytext.length*2);
   
   var clipid=Components.interfaces.nsIClipboard;
   
   if (!clip) return false;
   
   clip.setData(trans,null,clipid.kGlobalClipboard);
   
   }
   alert("Following info was copied to your clipboard:\n\n" + meintext);
   return false;
}
//-->
</script>
[/code]
[color=gray]
to call that script out of your HTML use e.g. this code:

<span onclick='return copy_clip("this is your personal text")'>
test this script:
click somewhere on this line to copy some text to your clipboard (you should have the text "Hello World, from http://www.krikkit.net!" in your clipboard afterwards)


notes about security:
a cause of the tight security settings in mozilla you have to sign the javascript to make it work another way is to change your firefox/mozilla settings

to do this add this line to your prefs.js file in your firefox/mozilla user profile directory

user_pref("signed.applets.codebase_principal_support", true);
or change it from within the browser with calling the "about:config" page

huge parts of the script are directly copied from the following sources:

http://www.xulplanet.com/tutorials/xultu/clipboard.html
http://www.codebase.nl/index.php/command/viewcode/id/174

Last Updated ( Monday, 13 February 2006 )  
[/color]

晚上再说,呵呵




Copyright © 1999-2000 LSLNET.COM. All rights reserved. 蓝森林网站 版权所有。 E-mail : webmaster@lslnet.com