如何识别一个网页是否正在加载一个iframe或直接进入浏览器窗口?
我正在写一个基于iframe的Facebook应用程序。 现在,我想使用相同的HTML页面来呈现正常的网站,以及Facebook中的canvas页面。 我想知道是否可以确定页面是否已经加载到iframe中或直接在浏览器中?
由于相同的源策略,浏览器可以阻止对window.top
访问。 IE的错误也发生。 这是工作代码:
function inIframe () { try { return window.self !== window.top; } catch (e) { return true; } }
top
和self
都是window
对象(和parent
window
),所以你会看到你的窗口是否是顶层窗口。
window.frameElement
返回embedded窗口的元素(如<iframe>或<object>);如果窗口是顶层,则返回null。 所以识别代码看起来像
if (window.frameElement) { // in frame } else { // not in frame }
这是标准而相当新的方法。 它完全适用于Chrome和Firefox。 我不能推荐它作为通用解决scheme,但应该在这里提到我想。
RoBorg是正确的,但我想添加一个附注。
在IE7 / IE8中,当微软向他们的浏览器添加了Tabs时,如果你不小心的话,他们打破了一件会对你的JS造成破坏的东西。
想象一下这个页面布局:
MainPage.html IframedPage1.html (named "foo") IframedPage2.html (named "bar") IframedPage3.html (named "baz")
现在在框架“巴兹”你点击一个链接(没有目标,加载在“baz”框架)它工作正常。
如果页面被加载,我们称之为special.html,使用JS来检查“它”是否有一个名为“bar”的父框架,它将返回true(预期)。
现在让我们来说一下在加载时的special.html页面,检查父框架(是否存在和它的名字,如果是“bar”,它会自动重新加载到框架中。
if(window.parent && window.parent.name == 'bar'){ window.parent.location = self.location; }
到现在为止还挺好。 现在来了错误。
可以说,不是像正常一样点击原始链接,而是在“baz”框架中加载special.html页面,您中间点击了它或者select了在新的Tab中打开它。
当新标签加载( 根本没有父框架! ) IE将进入一个无限的页面加载循环! 因为IE在JavaScript中“复制”了框架结构,使得新的标签具有父项,并且该父项具有名称“栏”。
好消息是,检查:
if(self == top){ //this returns true! }
在那个新的选项卡不会返回true,因此您可以testing这个奇怪的条件。
在Firefox 6.0 Extension(Addon-SDK 1.0)的内容脚本中,接受的答案不适用于我:Firefox在每个顶层窗口和所有iframe中执行内容脚本。
在内容脚本中,我得到以下结果:
(window !== window.top) : false (window.self !== window.top) : true
这个输出的奇怪之处在于,无论代码是在iframe还是在顶层窗口中运行,它总是一样的。
另一方面,谷歌浏览器似乎只能在顶层窗口中执行一次我的内容脚本,所以上述方法根本不起作用。
在这两个浏览器的内容脚本中最终为我工作的是这样的:
console.log(window.frames.length + ':' + parent.frames.length);
如果没有内嵌框架打印0:0
,则在包含一个框架的顶层窗口中打印1:1
,并在文档的唯一内联框架中打印0:1
。
这允许我的扩展在两个浏览器中确定是否存在任何iframe,并且如果在iframe之一内运行,则在Firefox中。
我正在使用这个:
var isIframe = (self.frameElement && (self.frameElement+"").indexOf("HTMLIFrameElement") > -1);
由于您是在facebook应用程序的上下文中询问的,因此您可能需要考虑在初始请求发生时在服务器上检测到这一点。 如果从iframe调用的话,Facebook将传递一堆查询string数据,包括fb_sig_user键。
由于您可能需要在应用程序中检查并使用这些数据,因此可以使用它来确定要呈现的相应上下文。
以这个javascript函数为例说明如何完成这个。
function isNoIframeOrIframeInMyHost() { // Validation: it must be loaded as the top page, or if it is loaded in an iframe // then it must be embedded in my own domain. // Info: IF top.location.href is not accessible THEN it is embedded in an iframe // and the domains are different. var myresult = true; try { var tophref = top.location.href; var tophostname = top.location.hostname.toString(); var myhref = location.href; if (tophref === myhref) { myresult = true; } else if (tophostname !== "www.yourdomain.com") { myresult = false; } } catch (error) { // error is a permission error that top.location.href is not accessible // (which means parent domain <> iframe domain)! myresult = false; } return myresult; }
我不知道这个例子是如何工作的,但我用IE浏览器,火狐浏览器和谷歌浏览器没有问题:
var iFrameDetection = (window === window.parent) ? false : true;
if(typeof(parent) == 'undefined') { console.log('Not Iframe'); } else { console.log('iframe'); }
如果您想知道用户是否从Facebook页面选项卡或canvas检查签名请求访问您的应用程序。 如果你没有得到它,可能用户没有从Facebook访问。 确保signed_request字段结构和字段的内容。
用php-sdk你可以得到这样的签名请求:
$signed_request = $facebook->getSignedRequest();
您可以在这里阅读更多关于签名请求:
https://developers.facebook.com/docs/reference/php/facebook-getSignedRequest/
和这里:
https://developers.facebook.com/docs/reference/login/signed-request/
这是我用过几次的一段古代代码:
if (parent.location.href == self.location.href) { window.location.href = 'https://www.facebook.com/pagename?v=app_1357902468'; }
if (window.frames.length != parent.frames.length) { page loaded in iframe }
但是,只有当您的页面和页面中的iframe数量不同时,才会将您加载到iframe中。 在你的页面没有iframe有这个代码的结果100%的保证
在每个页面写这个javascript
if (self == top) { window.location = "Home.aspx"; }
然后它会自动redirect到主页。
- 从用户访问令牌获取应用程序ID(或者validation源应用程序是否有令牌)
- 调用线程必须是STA,因为许多UI组件都需要这个
- FBSDKlogin错误代码:308在Objective-C中
- 这个应用程序的开发人员还没有正确设置这个应用程序的Facebooklogin?
- 获取所有用户朋友使用FacebookgraphicsAPI – Android的
- Facebook的Friends.getAppUsers使用Graph API
- facebook connect- $ user_id = $ facebook-> getUser(); 总是返回0
- 什么是获得持久令牌从服务器发布到Facebook粉丝页的步骤
- 为给定的URL获取Facebook /共享计数