如何从JavaScript访问父iframe


170

好吧,我有一个IFrame,它调用了相同的域页面。我的问题是我想从这个被调用的页面(通过JavaScript)访问该父iframe的某些信息。如何访问此iframe?

详细信息:由于我正在对Windows环境进行编程,因此有几个这样的iframe可以加载相同的页面。我打算关闭此iframe,这就是为什么我需要知道应该从他内部关闭哪个框架。我有一个数组,保留对这些iframe的引用。

编辑:有iframe是动态生成的


即使iframe是动态生成的,您也可以使用某种计数器分配新的唯一ID,最后您不需要知道ID,但是您可以轻松搜索,请参见我的答案。
Akash Kava 2012年

Answers:


138

您也可以将名称和ID设置为相等的值

<iframe id="frame1" name="frame1" src="any.html"></iframe>

这样您就可以在子页面中使用下一个代码

parent.document.getElementById(window.name);

16
也许对每个人来说都不是很明显,但是使用此方法,您可以访问父级的库对象(仅当父级已加载库时)。示例:使用parent。$('#something')访问jQuery
Zsolti 2013年

1
此解决方案与IE5 +兼容性古怪模式兼容。
Slayner '16

即使在2016年,它也可以很好地解决IE打印内容iframe太小的问题。但是为什么行得通呢?window.name返回一个字符串。window.name与仅将id名称作为不起作用的字符串传递相比,使用有什么不同?)?
卡尔

3
您好,它不与浏览器59运行..:VM111:1未捕获的抛出:DOMException:被阻止与原籍“帧XXX访问一个跨来源帧”。
Didier68年

如果未设置CORS,Chrome浏览器会在与跨源文件夹相同的文件夹中查看文件。他们说这是为了安全。设置CORS需要一台服务器。如果检测到Chrome,则向用户发送消息以设置服务器或更改浏览器。

90

只需致电 window.frameElement从框架页面。如果页面是不是在一个框架,然后frameElementnull

另一种方法(将window元素放入框架内比较简单),但出于完整性考虑:

/**
 * @param f, iframe or frame element
 * @return Window object inside the given frame
 * @effect will append f to document.body if f not yet part of the DOM
 * @see Window.frameElement
 * @usage myFrame.document = getFramedWindow(myFrame).document;
 */
function getFramedWindow(f)
{
    if(f.parentNode == null)
        f = document.body.appendChild(f);
    var w = (f.contentWindow || f.contentDocument);
    if(w && w.nodeType && w.nodeType==9)
        w = (w.defaultView || w.parentWindow);
    return w;
}

2
谢谢!适用于IE 6 +,FF和Chrome!
rustyx 2014年

11
window.frameElement返回null时,窗口和iframe有不同的领域,即跨来源消息。
Qwerty

@Qwerty您找到任何解决方案了吗?
Ajay Patidar

@AjayPatidar我想我放弃了。:(
Qwerty

78

我建议使用 postMessage API

在您的iframe中,致电:

window.parent.postMessage({message: 'Hello world'}, 'http://localhost/');

在页面中,您将包含iframe,您可以侦听以下事件:

window.addEventListener('message', function(event) {
      if(event.origin === 'http://localhost/')
      {
        alert('Received message: ' + event.data.message);
      }
      else
      {
        alert('Origin not allowed!');
      }

    }, false);

顺便说一句,还可以调用其他窗口,而不仅是iframe。

了解更多关于的postMessage API约翰Resigs博客在这里


7
我认为这显然是最好的答案,<iframe>内容不必了解父级,反之亦然。他们只需要遵守简单的消息合同。太棒了!
mfeineis 2014年

1
<iframe>仍然必须知道父级的域,对吗?
Homr Zodyssey

1
@HomrZodyssey父域仅作为安全机制可用,如果未知,则可以设置'*'
阿米尔·阿里·阿克巴里

'*'在客户端上使用。其他所有解决方案在Chrome浏览器上都会出错,因为未设置服务器,因此将clients文件夹中的文件视为不是Same Origin。这是最好的也是唯一的解决方案:dyn-web.com/tutorials/iframes/postmessage

30

老问题,但我只是遇到了同样的问题,并找到了获取iframe的方法。只需迭代父窗口的frames []数组,然后针对运行代码的窗口测试每个框架的contentWindow即可。例:

var arrFrames = parent.document.getElementsByTagName("IFRAME");
for (var i = 0; i < arrFrames.length; i++) {
  if (arrFrames[i].contentWindow === window) alert("yay!");
}

或者,使用jQuery:

parent.$("iframe").each(function(iel, el) {
  if(el.contentWindow === window) alert("got it");
});

此方法节省了为每个iframe分配ID的时间,这对于动态创建iframe很有用。我找不到更直接的方法,因为您无法使用window.parent获得iframe元素-它直接进入父窗口元素(跳过iframe)。因此,遍历它们似乎是唯一的方法,除非您想使用ID。


1
更新:这并没有完全按照广告宣传,我不得不使用contentWindow.document === document。不知道为什么。同样在某些浏览器中,我使用了contentDocument。好吧,我喜欢!
Christophe

1
抱歉,我只在Firefox中进行过测试。:)但是,我已经在多个浏览器中成功使用jQuery方法和contentWindow。
ingredient_15939

1
更新:我发现您也可以使用window.frameElement,但是我不确定哪些浏览器支持它。
Christophe

2
我认为这种类型的东西不再有用了。您会收到跨域错误。
安德鲁·毛

@AndrewMao的问题是关于同一原件的,所以没有理由提出跨源问题。
Christophe

21

您可以parent用来访问父页面。因此,要访问一个函数,它将是:

var obj = parent.getElementById('foo');

1
凯文(Kevin),问题在于知道ID。我有几个I帧,而我想从代码中访问它们
何塞·莱亚尔

仍然通过访问跨域框架而获得“将源为“ other-localhost:8000 ” 的框架阻止” 。
user2568374

13

设置iframe的ID后,您可以从内部文档访问iframe,如下所示。

var iframe = parent.document.getElementById(frameElement.id);

在IE,Chrome和FF中效果很好。


这似乎是一种复杂的工作方式var iframe = frameElement
Oriol 2015年

frameElement在当前窗口上下文中返回对象,但是parent.document.getElementById(frameElement.id)在父窗口上下文中返回对象,您无法使用frameElement运行父窗口的javascript函数,请在jsfiddle中尝试并给出示例,如果可以的话。
Akash Kava 2015年

6

也许只用

window.parent

进入您的iframe以获取调用框架/窗口。如果有多个呼叫帧,则可以使用

window.top

3

尝试此操作,在您的父框架中设置如下所示的IFRAME:

<iframe id="frame1" src="inner.html#frame1"></iframe>
<iframe id="frame2" src="inner.html#frame2"></iframe>
<iframe id="frame3" src="inner.html#frame3"></iframe>

请注意,每个帧的ID在src中作为锚传递。

然后在您的内部html中,您可以通过location.hash访问加载的框架的ID:

<button onclick="alert('I am frame: ' + location.hash.substr(1))">Who Am I?</button>

那么您可以访问parent.document.getElementById()从iframe内部访问iframe广告代码


是的,这将是最合理的解决方案,但有时我需要改变的iframe的src ..并通过这个散列或GET参数每个请求也不好..
何塞·莱亚尔

为什么每次传递哈希值都不好?它仅对浏览器可见,对服务器不可见,并且不会像get参数那样影响缓存。
Mark Porter

-1
// just in case some one is searching for a solution
function get_parent_frame_dom_element(win)
{
    win = (win || window);
    var parentJQuery = window.parent.jQuery;
    var ifrms = parentJQuery("iframe.upload_iframe");
    for (var i = 0; i < ifrms.length; i++)
    {
        if (ifrms[i].contentDocument === win.document)
            return ifrms[i];
    }
    return null;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.