如何识别网页是在iframe中加载还是直接加载到浏览器窗口?

aks*_*hat 554 javascript iframe facebook

我正在写一个基于iframe的Facebook应用程序.现在我想使用相同的html页面来呈现普通网站以及facebook中的画布页面.我想知道我是否可以确定页面是在iframe中加载还是直接在浏览器中加载?

Gre*_*reg 1033

window.top由于相同的原始策略,浏览器可以阻止访问.IE漏洞也会发生.这是工作代码:

function inIframe () {
    try {
        return window.self !== window.top;
    } catch (e) {
        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)

top并且self都是window对象(连同parent),所以你看到你的窗口是否是顶部窗口.

  • 这适用于IE 11,10和9.它也适用于FF和Opera,当然还有Chrome.我没有遇到任何问题. (14认同)
  • 好男人,8年后你的解决方案帮助我:) (9认同)
  • @sglessard如果子页面和父级来自不同的域,那么Firefox会抱怨同源策略(www.w3.org/Security/wiki/Same_Origin_Policy)并且代码不起作用 (7认同)
  • 在iframe中有一个iframe的页面,如果我的父iframe已嵌入页面中,则从我的子iframe进行测试,我使用if(parent === top) (5认同)
  • @james-gentes @greg 你能解释一下在什么情况下 `window.self !== window.top` 会抛出错误吗? (5认同)
  • 这似乎在Firefox中运行良好.它也适用于其他浏览器吗? (3认同)
  • 对于那些仍然摇摆着1995年最新技术的人来说,`window.self!== window.top`在`frame`,*或*`iframe`的内容中运行时返回`true`. (3认同)

Kon*_*nin 78

window.frameElement方法返回嵌入窗口的元素(例如iframeobject),或者null在顶级上下文中浏览:

window.frameElement
  ? 'embedded in iframe or object'
  : 'not embedded or cross-origin'
Run Code Online (Sandbox Code Playgroud)

这是一个HTML标准,在所有现代浏览器中都提供基本支持.

  • 在`iframe`的内部和外部获得`null` (4认同)
  • [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Window/frameElement)中的描述说"如果嵌入的文档具有不同的来源(例如已经来自不同的域名),这是空的." (4认同)
  • 请注意,根据[W3C](https://www.w3.org/TR/html5/browsers.html#dom-frameelement)([WHATWG],尝试读取`frameElement`会在跨域iframe中引发SecurityError异常(https://html.spec.whatwg.org/multipage/browsers.html#dom-frameelement)表示应返回null)。因此,您可能希望将其包装在`try ... catch`语句中。 (2认同)

scu*_*ffe 26

RoBorg是正确的,但我想添加一个旁注.

在IE7/IE8中,当微软将Tabs添加到他们的浏览器时,如果你不小心,他们就会破坏一件会对你的JS造成破坏的事情.

想象一下这个页面布局:

MainPage.html
  IframedPage1.html   (named "foo")
  IframedPage2.html   (named "bar")
    IframedPage3.html (named "baz")
Run Code Online (Sandbox Code Playgroud)

现在在框架"baz"中单击一个链接(没有目标,在"baz"框架中加载)它可以正常工作.

如果加载的页面,我们称之为special.html,使用JS检查"它"是否有一个名为"bar"的父框架,它将返回true(预期).

现在让我们说,在加载时,special.html页面会检查父框架(存在及其名称,如果它是"bar",它会在条形框架中重新加载.例如

if(window.parent && window.parent.name == 'bar'){
  window.parent.location = self.location;
}
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好.现在来了错误.

让我们说,不是像正常一样点击原始链接,而是在"baz"框架中加载special.html页面,您可以在其中间单击它或选择在新选项卡中打开它.

当新的选项卡加载时(根本没有父框架!)IE将进入无限循环的页面加载!因为IE"复制"JavaScript中的帧结构,使得新选项卡具有父项,并且该父项具有名称"bar".

好消息是检查:

if(self == top){
  //this returns true!
}
Run Code Online (Sandbox Code Playgroud)

在新的选项卡确实返回true,因此您可以测试这个奇怪的条件.


mag*_*noz 18

在Firefox 6.0 Extension(Addon-SDK 1.0)的内容脚本中,接受的答案对我不起作用:Firefox在每个中执行内容脚本:顶级窗口和所有iframe.

在内容脚本中,我得到以下结果:

 (window !== window.top) : false 
 (window.self !== window.top) : true
Run Code Online (Sandbox Code Playgroud)

关于此输出的奇怪之处在于,无论代码是在iframe内还是在顶级窗口中运行,它始终都是相同的.

另一方面,谷歌浏览器似乎只在顶级窗口中执行一次我的内容脚本,因此上述内容根本不起作用.

在两种浏览器的内容脚本中最终为我工作的是:

 console.log(window.frames.length + ':' + parent.frames.length);
Run Code Online (Sandbox Code Playgroud)

如果没有iframe 0:0,则会1:1在包含一个打印的框架的顶级窗口中打印,并在其打印的文档的唯一iframe中打印0:1.

这允许我的扩展程序在两个浏览器中确定是否存在任何iframe,另外在Firefox中如果它在其中一个iframe中运行.

  • 试试 `document.defaultView.self === document.defaultView.top` 或 `window !== window.top`。在 Firefox 的附加 SDK 的内容脚本中,全局 `self` 对象是一个用于与主脚本通信的对象。 (2认同)

小智 10

我不确定此示例如何适用于较旧的Web浏览器,但我将其用于IE,Firefox和Chrome而没有和问题:

var iFrameDetection = (window === window.parent) ? false : true;
Run Code Online (Sandbox Code Playgroud)

  • 窗口!== window.parent (9认同)
  • 或者只是`!(window === window.parent)` (6认同)

Bew*_*lam 10

if ( window !== window.parent ) 
{
      // The page is in an iframe   
} 
else 
{     
      // The page is not in an iframe   
}
Run Code Online (Sandbox Code Playgroud)

  • 除非您打开自己网站的 iframe。 (2认同)

小智 5

我正在使用这个:

var isIframe = (self.frameElement && (self.frameElement+"").indexOf("HTMLIFrameElement") > -1);
Run Code Online (Sandbox Code Playgroud)