【问题标题】:Using relative url for window.location in child iframe在子 iframe 中为 window.location 使用相对 url
【发布时间】:2011-01-17 20:21:12
【问题描述】:

我遇到了与 iframe 相关的问题。

我有一个带有 iframe(子)的文档(父)。如果父文档在子文档中调用一个函数,该函数使用 window.location 将孩子的 url 更改为相对 url,则该 url 将相对于父文档。让我举例说明。

父文档:/test/parent.html

子文档:/projects/child.html

子代码:

function moveOn(){
    window.location.href = "newPage.html";
}

父代码:

childDocument.contentWindow.moveOn();

结果: 子文档尝试访问 /test/newPage.html 而不是 /projects/newPage.html

有没有办法从父母那里解决这个问题?我处于无法在子文档代码中进行更改的情况,只能在父文档中进行更改。

谢谢, 尼克

编辑:

这是实际代码

在父级(/testr/testr.html)中:

testr.appHolder = $("childIframe"); 
testr.appHolder.src = "../projects/test.html"; 
testr.functionName = "moveOn"; 
testr.appHolder.contentWindow[testr.functionName]();

在子 (/projects/test.html) 中:

function moveOn(){ 
  window.location.href = "newPage.html"; 
}

这是实际代码

在父级(/testr/testr.html)中:

testr.appHolder = $("childIframe"); 
testr.appHolder.src = "../projects/test.html"; 
testr.functionName = "moveOn"; 
testr.appHolder.contentWindow[testr.functionName]();

在子 (/projects/test.html) 中:

function moveOn(){ 
  window.location.href = "newPage.html"; 
}

【问题讨论】:

  • 嗯?您是否 10000% 确定这会以您描述的方式发生?那将是奇怪的。如果您从子窗口中调用moveOn,它肯定会重定向到不同的 URL?
  • .. 顺便欢迎来到 SO。
  • 谢谢!。请使用格式正确的代码查看下面的评论。
  • 我遇到了完全相同的问题,除了相反(我希望孩子控制父母相对于父母的网址)。不过情况完全一样。
  • 发生这种“明显令人惊讶”的行为是因为代码在父级的上下文中运行,这意味着任何相对 url 都相对于父级进行解释。在某些方面,实际上是有道理的。如果它以另一种方式起作用,人们也会将其描述为令人困惑。 :)

标签: javascript iframe path location


【解决方案1】:

HTML 规范说:

当设置 [location 属性] 时,[browser] 必须解析参数,相对于入口脚本的基本 URL,如果成功,则必须将浏览上下文导航到指定的 url。

获得您所追求的行为的一种(hacky)方法是直接编辑locationpathname 属性:自己有效地实现相对网址的解析。

在您的情况下,您将使用您孩子的现有网址“手动”编辑网址。

点点解决方案

一个“聪明”的方法是通过附加一个斜杠将文件名变成一个“目录”,然后用一个“点”删除它,然后是你想要的相对网址。

childDocument.contentWindow.location.pathname += "/../newPage.html";

(此代码也可以在子代码中运行,但您提到无法更改子代码。)

看看它是如何工作的。

路径开头为
/projects/child.html

然后你追加它,得到
/projects/child.html/../newPage.html

浏览器将此解析为
/projects/newPage.html

很遗憾,我想这对您来说不是一个完美的解决方案。听起来每个“子”页面都包含指向链中下一页的硬编码链接,可以是任何页面。获取任何给定子页面的“下一个”相对 url 需要孩子的合作。

如果子页面以可预测的方式命名,并且您知道页面总数,并且您知道子目录的基本 url,那么您可以让父级正确控制子级。有很多如果。

旁注:我正在寻找一种更优雅、更强大的解决方案。手指交叉。

【讨论】:

    【解决方案2】:

    啊哈。我找到了baseURI 属性。现在我们正在讨论。

    根本问题是正在执行代码的文档(父级)的baseURI 设置为父级的位置。您希望在更改页面位置之前将页面的 baseURI 设置为与孩子的位置相同,以便在孩子的上下文中解析相对 url。

    简而言之,可以这么说:

    var originalURI = document.baseURI; // store for setting back after the move
    document.baseURI = childDocument.location; // setting parent's baseURI (NO EFFECT!)
    childDocument.contentWindow.moveOn();
    document.baseURI = originalURI; // restore original baseURI
    

    很遗憾,baseURI 属性是只读。幸运的是,它的值取自 <base> 标记,您可以使用脚本对其进行更改。您可以通过将父级的基本标记设置为引用 childUrl 来获得给定子级所需的功能:

    <head>
    <base href="/path/to/child.html" />
    </head>
    

    不幸的是,这会使您的父级中的 任何 相对链接相对于子级,这不是您想要的。我们需要在点击链接后设置它,并在孩子被告知moveOn()后重新设置。

    如果您在父母的&lt;head&gt; 中包含一个空的&lt;base /&gt; 标记,默认情况下它不会影响baseURI。所以当你想在child中执行moveOn()函数时,你可以这样说:

    var baseElement = document.getElementsByTagName("base")[0];
    
    // adopt the child's location as baseURI
    baseElement.href = childDocument.location; 
    
    childDocument.contentWindow.moveOn();
    
    // revert back to the parent's original baseURI
    baseElement.removeAttribute("href"); 
    

    (希望这能有所帮助 - 两年后......哈)

    编辑:

    Internet Exploder 再一次成为派对的垃圾。似乎不尊重加载后对任何标签的更改。因此,除非您不必支持 IE(哈哈!),否则除非您乐于将孩子的位置硬编码到父母的标签中,否则此解决方案将不起作用。同样,这些都是大如果。

    【讨论】:

      【解决方案3】:

      终于,一个完整的解决方案!

      childDocument.contentWindow.setTimeout( childDocument.contentWindow.moveOn, 0 );
      

      这要求子文档在零毫秒内执行给定的函数 (moveOn),并且在子文档的上下文中执行,即使在 Internet Exploder 中也是如此。

      嘘。

      【讨论】:

      • 对所有帖子感到抱歉。我认为这是您唯一需要的。
      • 仅仅过了 4 年,我对这项研究完全没有记忆。 ://
      猜你喜欢
      • 2011-09-22
      • 1970-01-01
      • 1970-01-01
      • 2014-12-06
      • 2013-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多