skip to Main Content

I looked at other solutions here in SO 1, 2 but none of the solutions work for me. Consider following code:

<!DOCTYPE html>
<html>
  <head>
    <title>Opening window with JS</title>
    <script>
      const openWindow = () => {
        const win = window.open('', '_blank', 'top=20, left=20, width=200, height=200');
        win.document.addEventListener('DOMContentLoaded', () => {
          console.info('Child window loaded');
          win.document.body.style.background = 'hotpink';
        });
      }

      document.addEventListener('DOMContentLoaded', (_) => {
        document.getElementById('open').addEventListener('click', (_) => openWindow())
      })
    </script>
  </head>
  <body>
    <button id="open">Open window</button>
  </body>
</html>

When the window is opened, I don’t see anything logged into the console and background of the page is not changed.

I also tried adding this to my <script> tag:

const openWindow = () => {
  const win = window.open('', '_blank', 'top=20, left=20, width=200, height=200');
  win.onload = () => {
    console.info('Child window loaded');
    win.document.body.style.background = 'hotpink';
  };
}

document.addEventListener('DOMContentLoaded', (_) => {
  document.getElementById('open').addEventListener('click', (_) => openWindow())
})

That doesn’t work either. So next step was to try embedding JS into the HTML of the newly opened window (the </script> is not a typo, it has to be escaped in literal):

      const openWindow = () => {
      const win = window.open('', '_blank', 'top=20, left=20, width=200, height=200');
      win.document.write(`
      <!DOCTYPE html>
      <html>
        <head>
          <title>Child window</title>
          <script>
            const handleOnLoad = () => {
              console.info('Child window loaded');
              window.body.style.background = 'hotpink';
            }
          </script>
        </head>
        <body onload="handleOnLoad">
        </body>
      </html>
      `);
      }

    document.addEventListener('DOMContentLoaded', (_) => {
      document.getElementById('open').addEventListener('click', (_) => openWindow())
    })

However that doesn’t bring me any closer. How do I proceed?

3

Answers


  1. It’s a matter of timing

    The issue with the code may be that it is trying to add a DOMContentLoaded event listener to the child window’s document before it is loaded. This means that the event listener is not actually added successfully.

    One way to solve this is to move the event listener to the child window’s HTML code and call a function defined in the parent window to change the background color.

    Login or Signup to reply.
  2. You need to use the document.readyState method and wait to be complete:

    For infomation, the document.readyState complete :

    The document and all sub-resources have finished loading. The state indicates that the load event is about to fire.

    You can resolve your issue with adding a setInterval to check when the new window readState is equal to complete and clear the setInterval() when readystate is complete.

    <!DOCTYPE html>
    <html>
    
    <head>
        <title>Opening window with JS</title>
        <script>
            const openWindow = () => {
            const win = window.open('', '_blank', 'top=20, left=20, width=200, height=200');
            const intervalId = setInterval(() => {
                if (win.document.readyState === 'complete') {
                    clearInterval(intervalId);
                    console.info('Child window loaded');
                    win.document.body.style.background = 'hotpink';
                }
            }, 100);
        };
    
        document.addEventListener('DOMContentLoaded', () => {
            const openButton = document.getElementById('open');
            openButton.addEventListener('click', () => {
                const win = openWindow();
            });
        });
    </script>
    </head>
    
    <body>
        <button id="open">Open window</button>
    </body>
    
    </html>
    
    Login or Signup to reply.
  3. @Eureka is right.

    You open a new window without a location, that is ready before your next line where you bind the listener. I also doubt that it’s seen as DOMContent, because there is none in reality. But I am not sure about that.

    Secondly, you need to reference the mainwindow to pass information to.
    Third, you didn’t mention this, but if you open a site on an other domain, you will run into CORS issues. For example, try another website on the line otherWin.location = '' and whatch the console error.

    What I come up is a fiddle that shows what happens:

    let otherWin = window.open('', '_blank', 'top=20, left=20, width=200, height=200');
    let mainWindow = window;
    otherWin.onload = function(event){
        mainWindow.console.info('Child window loaded');
      let childWindow = this;
    };
    otherWin.document.onDOMContentLoaded = function(event){
        mainWindow.console.info('Child document content loaded');
      let childWindowDocument = this;
      this.body.style.background = 'hotpink';
    };
    // events didnt fire because window was ready (empty page!) before listeners attached
    
    otherWin.location = ''; // try different website urls here!
    console.log(otherWin.document.childNodes.length);
    console.log(typeof otherWin.onload);
    console.log(typeof otherWin.document.onDOMContentLoaded);
    setTimeout(function(){ 
            console.log('After waiting 5 seconds....');
            console.log(typeof otherWin.onload);
            console.log(typeof otherWin.document.onDOMContentLoaded); // not available anymore, document changed due our location!
            console.log(otherWin.document.childNodes.length); //
      }, 
      5000
    );
    

    Console shows

    1
    "function"
    "function"
    "Child window loaded"
    "After waiting 5 seconds...."
    "function"
    "undefined"
    2
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search