2

is it possible to inject a javascript function, defined inside an iframe, into the parent window, so that it is available even after the removal of the iframe? Here is what I do: in the iframe I have:

var f = function(){console.log("iframe function")}
window["iframeFunction"] = f;

The parent can successfully call the function until the iframe is available..afterwards it doesn't work.

Emmanuel N
  • 7,350
  • 2
  • 26
  • 36
Francesco S.
  • 53
  • 1
  • 8
  • Why don't you define the function in the window's scope and use it in iframe? Or something like including the JS file in home page rather – hop Mar 15 '13 at 14:46
  • You could try to make a copy, in the parent window. http://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-clone-a-javascript-object – Maresh Mar 15 '13 at 14:49

2 Answers2

0

Suppose this is your iframe (ifr.htm)-

<html>
<head>
    <script type="text/javascript">
        function func() {
            window.top.window.f = function() {
                alert('iframe hack');
            }
        }
        window.onload = function() {
            alert('iframe loaded');
            func();
        };
    </script>
</head>
<body>
    this is the test iframe.
</body>
</html>

and this is your parent window-

<html>
<head>
    <script type="text/javascript">
        window.onload = function() {
            i = document.getElementById('iframe'); //remove the iframe
            i.parentNode.removeChild(i);
            window.f(); //you can still call f() method     
        };
    </script>
</head>
<body>
    this is the parent window.
            <iframe src="ifr.htm" id="iframe"></iframe>
</body>
</html>

This basically accesses the parent using top and adds a function to it. So even when the iframe is removed from the DOM, the function will still remain, as it was added to the parent.

ShuklaSannidhya
  • 8,572
  • 9
  • 32
  • 45
  • @FrancescoS. How do you remove the iframe in IE? – ShuklaSannidhya Mar 15 '13 at 15:38
  • 1
    var obj = document.getElementById('iframe'); obj.parentNode.removeChild(obj); – Francesco S. Mar 15 '13 at 15:40
  • @FrancescoS. Updated code. Now it is working fine in IE8. Just make sure to drop out ` ` because IE8 does not support HTML5 Doctype. – ShuklaSannidhya Mar 15 '13 at 15:45
  • Ok I found an error.. var p = obj.parentNode; p.removeChild(obj); is better..I have an error because console is undefined..why? anyway with an alert I can see the message after the iframe closure. This however doesn't work if I change the src attribute of the iframe..at least in IE..any idea?? Thanks!! – Francesco S. Mar 15 '13 at 15:46
  • @FrancescoS. My bad, IE does not support `console` so change `console.log` to `alert`. If you change `src` attribute after iframe has loaded, it will still work. – ShuklaSannidhya Mar 15 '13 at 15:49
0

Depending on browser support requirements, I would recommend postMessage. The advantages are:

  1. Don't need to pollute parent's global namespace (less chance of collision / availability outside of desired scope)
  2. Parent is notified of new function's availability (rather than assuming or polling for change)

EDIT: Even if you want to have the function available in the global namespace of the parent with the label specified by the iframe, point 2 still applies.

The code:

// In your iframe
var f = function(){console.log("iframe function")}
window.top.postMessage({f:f}, '*');

// In the parent
window.addEventListener('message', function capturePassedFunction(e){
    // If you want to keep this in scope
    var f    = e.data.f;
    // You can still chuck it on the `window` object if you want!
    window.f = e.data.f;
}, false);
Barney
  • 16,181
  • 5
  • 62
  • 76
  • Unfortunately I'm using IE8/9 and it seems that it doesn't work: addEventListener is not recognized – Francesco S. Mar 15 '13 at 15:06
  • Older IEs would use `window.attachEvent("onmessage", function capturePassedFunction(e){…})`. If you're using jQuery, you can just use `$(window).on('message', function capturePassedFunction(e){var f = e.originalEvent.data.f …})` – Barney Mar 15 '13 at 15:12