How to call function of another iframe

2020-04-15 20:54发布

问题:

I'm trying to call iframe2 function from iframe1

  document.getElementById('cDiv').contentWindow.toggle_main();
   var iframe = document.getElementsByTagName('iframe')[1];
  iframe.contentWindow.myFunction();

The console is returning Uncaught TypeError: Cannot read property 'contentWindow' of undefined

I have also tried:

   window.frames['iframe2'].toggle_main();

The function in iframe2 is called:

 <script>

 window.myFunction = function(args) {
  alert("called");    
 }
 </script>

The iframes are defined as:

<DIV id="cgDiv">
<IFRAME  id="contentGenerator" SCROLLING="No"  name ="iframe1" src="outlook.html">
</IFRAME>
</DIV>
<DIV id="cDiv">
<IFRAME id="content" SCROLLING="AUTO" verticalscrolling="yes"  NAME = "iframe2" src="index.html">
</IFRAME>
</DIV>

Ideas on where the problem should be?

回答1:

Javascript can't access functions in an IFrame directly. IFrames can access functions in their parent though.

So if your main page exposes a method RegisterCallback for instance, the IFrame can call it with one of its functions as parameter. The page can then store a reference to the function and call it at another time (with any parameters...)

UPDATE: Added example code

The code below is two files; index.html which is the master page with iframe(s), and child.html which is the page inside the iframe(s).

I've committed the example to github and you can test it by following this link. Due to browser security restrictions the code must be loaded from the same webserver and doesn't work if run directly from the filesystem.

I've intentionally included the child iframe twice to illustrate that any number of children can be registered with this technique. I leave it as an excercise to the reader to add a third iframe... :)

index.html

<html>
<body style="background:#efe">

    <h1>This is the master page</h1>
    <p><button id="setChildButton" type="button">Make child blue</button></p>
    <iframe src="child.html"></iframe>
    <iframe src="child.html"></iframe>
</body>
</html>
<script>
    var childCallbacks = [];

    function registerChild(callback){
        console.log('Registering child callback');
        childCallbacks.push(callback);
    }

    function onButtonClick(){
        for (var i=0; i < childCallbacks.length; i++){
            var callback = childCallbacks[i];
            callback('blue');
        }
    }

    window.onload = function(){
        document
            .getElementById('setChildButton')
            .addEventListener('click', onButtonClick);
    };
</script>

The javascript has a function registerChild() that it never calls itself, but can be called from child pages to register their endpoints.

When the button is clicked, all registered callbacks are called with the string "blue". It is then up to the childs endpoint to do something good with that. In this case changing its own background color.

child.html

<html>
<body id="childBody" style="background:#fee">
    <h2>This is the child page</h2>
</body>
</html>
<script>

    function setBackground(color){
        var body = document.getElementById('childBody');
        body.style.backgroundColor = color;
    }

    window.onload = function(){
        if (parent && parent.registerChild){
            console.log('registering with parent');
            parent.registerChild(setBackground);
        }
    };
</script>

The javascript of the child checks if there is a parent (it is running inside an iframe) and that the parent provides a function called registerChild(). It then calls that function with a reference to its own function setBackground().

When the parent later calls the callback with the string "blue", it turns around and sets its own bodys background color to that value.



回答2:

If all your documents share same origin, it should work, so calling

window.parent.frames['other frame name'].contentWindow['func']()

from within some frame will invoke func from neigbour iframe.

Behold hacky simplistic datauri example in Firefox (Chrome considers dataURI documents as always different origin, so it raises security exception)

data:text/html;charset=utf-8,<iframe id="a" src="data:text/html,<h1 id=a>0</h1><script>function inc(){a.innerHTML++}</script>"></iframe><iframe id="b" src="data:text/html,<button onclick=window.parent.frames.a.contentWindow['inc']()>inc in prevous frame</button>"></iframe>


回答3:

// First iframe called (ifr_url) in Master page.
// Second iframe called (ifr_tab5) inside the master page.
// I want to call function (Hallow()) in second iframe.

var win = document.getElementById("ifr_url"); // reference to iframe's window
var doc = win.contentDocument? win.contentDocument : win.contentWindow.document;
var form = doc.getElementById('ifr_tab5').contentWindow.Hallow();