'Problem: Javascript iframe send the postMessage() before iframe completed loading

I have iframe in parent.html. Child.html sending the postMessage('documnent.cookie','*') to the parent window.

The problem is postMessage() send 'null'. postMessage() is triggered before iframe loading is completely done. I have to postMessage() to Parent window only if iframe completely loads the data.

Here is my code: parent.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">

<body id="Body" style="background-color:Silver">

  <iframe id ="CA_FRAME_0" src="http://localhost/ibmcognos/bi/child.html" style="display:none"></iframe>

  <script type="text/javascript">  

    window.addEventListener("message", function (e){   


    if(e.data == null){         
        alert('fail');                

    }else{      
        alert('sucess');           
        document.cookie="key=" +e.data + ";expires=0;path=/";           
    }       

    }, false);  


</script>

<div id="arcContainer" class="arcContainer"></div>  

    <script type="text/javascript">     

        ARCPLAN.language = "XXX";
        ARCPLAN.application = "lv02";
        ARCPLAN.startDocName = "application.apa";
        ARCPLAN.arcCgiSite = "http://localhost/.....";      

    </script>
</body>
</html>

//child.html

 <!DOCTYPE html> <html> <head>
    <title>COOKIE</title>
    <meta http-equiv="X-UA-Compatible" content="IE=edge" /> </head> <body>

<script type="text/javascript">

    function getCookie(name) {      var arg = name + "=";       var alen = arg.length;      var clen = document.cookie.length;      var i = 0;      while(i < clen) {           var j = i
+ alen;             if(document.cookie.substring(i, j) == arg)
                return getCookieVal(j);             i = document.cookie.indexOf(" ", i) + 1;            if(i == 0)
                break;      }       return null;    }

    function getCookieVal(offset) {         var endstr = document.cookie.indexOf(";", offset);      if(endstr == -1)            endstr = document.cookie.length;        return document.cookie.substring(offset, endstr);   }   
            **parent.postMessage(getCookie("key"), "*");**   </script>

**<iframe id ="CA_FRAME" src="http://localhost/ibmcognos/bi/" style="display: none;" ></iframe>**   - *this url make the redirect from here and set the cookie, it takes time* 

</body> </html>

Kindly provide me some suggestions. Thanks.



Solution 1:[1]

In this case we have a webpage A need to load another webpage B through iframe. page A is loaded. we can add a custom event to listen page B load event.

page A code:

const iframeWin = document.getElementById('h5-iframe').contentWindow;
window.addEventListener(
  'message',
  (e) => {
    const { data } = e;
    console.log('receive page load', data);
    if (data.pageLoaded) {
      iframeWin.postMessage(youdata, '*');
    }
  },
  false,
);

page B code:

window.addEventListener(
  'message',
  (e) => {
    console.log('receive youdata', data);
    const { data } = e;
  },
  false,
);

// after register listen function send this message to page A.
window.parent.postMessage({ pageLoaded: true }, '*');

Solution 2:[2]

Add an onload event to your iFrame:

<iframe id ="CA_FRAME" src="http://localhost/ibmcognos/bi/" onload="onCaFrameLoad(this)" style="display: none;"></iframe>

Then you can run JS code only after the frame has completely loaded:

function onCaFrameLoad() {
    // wrap your post in this function
};

This way, the code will only run once the frame has finished loading.

PoC: parent.html

<html>
    <body>
        PARENT- I get data from child
        <br /><br />
        <iframe id ="CA_FRAME_0" src="child.html"></iframe>
    </body>
</html>

child.html

<html> 
    <body>
        CHILD - I send data to parent - but only after CA_FRAME has loaded
        <br /><br />
        <iframe id ="CA_FRAME" src="inner.html" onload="onCaFrameLoad(this)"></iframe>
        <script>
            function onCaFrameLoad() {
                alert('iframe has loaded! now you can send data to the parent');
            };
        </script>
    </body>
</html>

inner.html

<html> 
    <body>
        INNER - I load all my content, then the onCaFrameLoad function in child.html runs
        <script>
        alert('My Name is INNER - I load all my content first');
        </script>
    </body>
</html>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 PeakFish
Solution 2