从父页面调用iframe中的JavaScript代码

从父页面调用iframe中的JavaScript代码,javascript,html,iframe,Javascript,Html,Iframe,基本上,我在页面中嵌入了一个iframe,而iframe有一些我需要从父页面调用的例程 现在相反的情况非常简单,因为您只需要调用parent.functionName(),但不幸的是,我需要的正是相反的情况 请注意,我的问题不是更改iframe的源,而是调用iframe中定义的函数有一个错误 由于该页面现在已被破坏,只能通过archive.org访问,因此我在此处复制了它: IFrames 在这一页上,我简要概述了如何从iFrame所在的页面访问iFrame。不足为奇,这里有一些浏览器方面的考虑

基本上,我在页面中嵌入了一个
iframe
,而
iframe
有一些我需要从父页面调用的例程

现在相反的情况非常简单,因为您只需要调用
parent.functionName()
,但不幸的是,我需要的正是相反的情况

请注意,我的问题不是更改
iframe
的源,而是调用
iframe
中定义的函数有一个错误

由于该页面现在已被破坏,只能通过archive.org访问,因此我在此处复制了它:

IFrames

在这一页上,我简要概述了如何从iFrame所在的页面访问iFrame。不足为奇,这里有一些浏览器方面的考虑

iframe是一个内联框架,虽然它包含一个完全独立的页面和它自己的URL,但它仍然被放在另一个HTML页面中。这为网页设计提供了很好的可能性。问题是访问iframe,例如加载一个新页面。本页介绍如何执行此操作

帧或对象?

基本问题是iframe是被视为一个框架还是一个对象

  • 如页面上所述,如果使用框架,浏览器将为您创建框架层次结构(
    top.frames[1].frames[2]
    等)。iframe是否适合此框架层次结构
  • 或者浏览器是否将iframe视为另一个对象,即恰好具有src属性的对象?在这种情况下,我们必须使用标准(如
    document.getElementById('theiframe'))
    来访问它。 一般来说,浏览器允许在“真实”(硬编码)iframe上同时显示这两个视图,但生成的iframe不能作为帧访问
名称属性

最重要的规则是为您创建的任何iframe提供一个
name
属性,即使您也使用
id

<iframe src="iframe_page1.html"
    id="testiframe"
    name="testiframe"></iframe>
语法。据我所知,这总是有效的

访问文档

如果使用
name
属性,访问iframe中的文档非常简单。要计算iframe中文档中的链接数,请执行以下操作

生成的iFrame

当您通过生成iframe时,iframe不会立即输入到
frames
数组中,而且
frames['testiframe'].location.href
语法将无法立即工作。在iframe出现在数组中之前,浏览器需要一点时间,在此期间,任何脚本都不能运行

document.getElementById('testiframe').src
语法在所有情况下都能正常工作

链接的
target
属性也不适用于生成的iframe,Opera除外,尽管我给了生成的iframe一个
名称和一个
id

<iframe src="iframe_page1.html"
    id="testiframe"
    name="testiframe"></iframe>
缺少
target
支持意味着您必须使用JavaScript来更改生成的iframe的内容,但由于您首先需要JavaScript来生成它,因此我认为这并不是什么大问题

iFrame中的文本大小

一个奇怪的Explorer 6唯一的bug:


通过“视图”菜单更改文本大小时,iFrame中的文本大小将正确更改。但是,此浏览器不会更改原始文本中的换行符,因此部分文本可能会不可见,或者换行符可能会在换行符仍可以容纳另一个单词时出现。

假设您的iFrame的id为“targetFrame”,并且要调用的函数为
targetFunction()

您还可以使用
window.frames
而不是
document.getElementById
访问框架

// this option does not work in most of latest versions of chrome and Firefox
window.frames[0].frameElement.contentWindow.targetFunction(); 

IFRAME应该位于
frames[]
集合中。使用类似

frames['iframeid'].method();

在IFRAME中,将函数公开给窗口对象:

window.myFunction = function(args) {
   doStuff();
}
要从父页面访问,请使用以下命令:

var iframe = document.getElementById("iframeId");
iframe.contentWindow.myFunction(args);

这里有一些怪癖需要注意

  • htmliframelement.contentWindow可能是更简单的方法,但它不是一个标准属性,一些浏览器不支持它,大多数是旧的。这是因为DOM Level 1 HTML标准对
    窗口
    对象没有任何规定

  • 您还可以尝试
    htmliframelement.contentDocument.defaultView
    ,这是一些较旧的浏览器允许的,但IE不允许。即便如此,该标准也没有明确规定您可以取回
    窗口
    对象,原因与(1)相同,但如果您愿意,您可以在这里选择一些额外的浏览器版本

  • window.frames['name']
    返回窗口是最古老的,因此也是最可靠的接口。但是您必须使用
    name=“…”
    属性才能按名称获取帧,这有点难看/不推荐/过渡。(
    id=“…”
    会更好,但IE不喜欢这样。)

  • window.frames[number]
    也非常可靠,但知道正确的索引是关键。如果你知道你的页面上只有一个iframe,你可以不受惩罚

  • 完全有可能是子iframe尚未加载,或者是由于其他原因导致无法访问。您可能会发现反转通信流更容易:也就是说,当子iframe完成加载并准备回调时,让子iframe通知其
    窗口.parent
    脚本。通过将自己的一个对象(例如回调函数)传递给父脚本,该父脚本就可以直接与iframe中的脚本通信,而不必担心它与哪个htmliframelement关联


  • 为了记录在案,我今天遇到了同样的问题,但这次页面嵌入了一个对象,而不是一个iframe(因为它是一个XHTML1.1文档)。以下是它如何处理对象:

    document
      .getElementById('targetFrame')
      .contentDocument
      .defaultView
      .targetFunction();
    
    )对不起
           $("#myframe").load(function() {
                alert("loaded");
            });
    
    document
      .getElementById('targetFrame')
      .contentDocument
      .defaultView
      .targetFunction();
    
    window.location.reload();
    
    window.parent.location.reload();
    
    var el = document.getElementById('targetFrame');
    
    if(el.contentWindow)
    {
       el.contentWindow.targetFunction();
    }
    else if(el.contentDocument)
    {
       el.contentDocument.targetFunction();
    }
    
    var o = document.getElementsByTagName('iframe')[0];
    o.contentWindow.postMessage('Hello world', 'http://b.example.org/');
    
    window.addEventListener('message', receiver, false);
    function receiver(e) {
      if (e.origin == 'http://example.com') {
        if (e.data == 'Hello world') {
          e.source.postMessage('Hello', e.origin);
        } else {
          alert(e.data);
        }
      }
    }
    
    window.parent.targetFunction();
    
    function getIframeWindow(iframe_object) {
      var doc;
    
      if (iframe_object.contentWindow) {
        return iframe_object.contentWindow;
      }
    
      if (iframe_object.window) {
        return iframe_object.window;
      } 
    
      if (!doc && iframe_object.contentDocument) {
        doc = iframe_object.contentDocument;
      } 
    
      if (!doc && iframe_object.document) {
        doc = iframe_object.document;
      }
    
      if (doc && doc.defaultView) {
       return doc.defaultView;
      }
    
      if (doc && doc.parentWindow) {
        return doc.parentWindow;
      }
    
      return undefined;
    }
    
    ...
    var el = document.getElementById('targetFrame');
    
    var frame_win = getIframeWindow(el);
    
    if (frame_win) {
      frame_win.targetFunction();
      ...
    }
    ...
    
    function tunnel(fn) {
        fn();
    }
    
    var myFunction = function() {
        alert("This work!");
    }
    
    parent.tunnel(myFunction);
    
    parent.document.getElementById('frameid').contentWindow.somefunction()
    
    <button id='parent_page_button' onclick='call_button_inside_frame()'></button>
    
    function call_button_inside_frame() {
       document.getElementById('my_iframe').contentWindow.postMessage('foo','*');
    }
    
    window.addEventListener("message", receiveMessage, false);
    
    function receiveMessage(event)
        {
          if(event) {
            click_button_inside_frame();
        }
    }
    
    function click_button_inside_frame() {
       document.getElementById('frame_button').click();
    }
    
    document.getElementById('my_iframe').contentWindow.postMessage('foo','*');
    
    window.parent.postMessage('foo','*')