Window: postMessage() method

jemand anders

Erfahrenes Mitglied
Hallo,

wenn ich die postMessage()-Testapplikation starte, wird die zweite Seite zwar aufgebaut, aber
  • die Rückmeldung erfolgt erst beim zweiten Aufruf, und
  • das Input-Feld wird beim ersten Aufruf gar nicht und ansonsten nur temporär gefüllt und direkt wieder geleert.
Jemand eine Idee, wie es hinbekomme, dass beim ersten Aufruf die Rückmeldung erfolgt und das Input-Feld den Wert behält?

Freundl. Grüße

HTML:
<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width" />
    <title>messageChannelPage1a.html</title>
  </head>
  <!-- https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage -->
  <body>
    <p>messageChannelPage1a.html</p>
    <script>
      var popup = window.open(
        'messageChannelPage2a.html',
        'popup',
        'toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=600,height=1100,top=0, left=1250'
      )
      popup.focus()

      popup.postMessage(
        JSON.stringify({
          message: 'myMessageText...',
          location: window.location.href
        }),
        window.location.href //"http://localhost/messageChannelPage1a.html");
      )

      window.addEventListener(
        'message',
        event => {
          //if (event.origin !== "./messageChannelPage1a.html") return;
          console.log(event.source, event.data)
        },
        false
      )
    </script>
  </body>
</html>

HTML:
<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width" />
    <title>messageChannelPage2a.html</title>
  </head>
  <body>
    <p>messageChannelPage2a.html</p>

    <input type="text" name="input1" id="input1" />

    <script>
      console.clear()

      window.addEventListener('message', event => {
        // if (event.origin !== "./messageChannelPage1a.html") return;
        const data = JSON.parse(event.data)
        document.querySelector('input').value =
          data.message + ' ' + data.location

        event.source.postMessage(
          'Message von Page 2' +
            event.source.window.location.href +
            ' ' +
            data.message +
            ' ' +
            data.location,
          event.origin
        )
      })
    </script>
  </body>
</html>
 
Zuletzt bearbeitet:
Dann bist Du mir ja zuvor gekommen. Ich wollte gerade schreiben, dass man bei MDN liest:
When window.open() returns, the window always contains about:blank. The actual fetching of the URL is deferred and starts after the current script block finishes executing. The window creation and the loading of the referenced resource are done asynchronously.
Ich könnte mir noch eine andere Lösung ohne setInterval vorstellen: Die zweite Seite, die Du öffnest, sendet beim load-Event eine Fertig-Nachricht an die Masterseite um zu signalisieren, dass sie fertig geladen ist.
 
Mit window.opener bekommst Du das window-Objekt, von dem aus die zweite Seite geöffnet wurde. Also, auf der zweiten Seite, ungetestet und einfach so hin geschrieben:
Code:
addEventListener("load", (event) => {
    window.opener.postMessage('page-ready');
});
Dein Listener auf der Masterseite wird das empfangen und Du kannst darauf reagieren.

Und Du hast fest gestellt, dass es cross-origin nicht funktioniert. Bei MDN lese ich jedoch:
safely enables cross-origin communication between Window objects;
D. h. durch irgend welche Parameter etc. sollte es gehen.
 
"Und Du hast fest gestellt, dass es cross-origin nicht funktioniert. Bei MDN lese ich jedoch:"
Hatte einen Fehler drin…

Die Opener-Sache werde ich jetzt mal testen.
 
Eigentlich war meine Absicht, Werte aus dem Window A via postMessage an Window B cross-damain zu übergeben, dort in ein Formular zu übertragen und in einer lokalen Datenbank zu speichern, aber das klappt überhaupt nicht, und habe keinen Schimmer, warum nicht. Vielleicht kann mich jemand aufklären.

HTML:
<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width" />
    <title>messageChannelPage1a.html</title>
  </head>
  <!-- https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage -->
  <body>
    <p>messageChannelPage1a.html</p>

    <script>
      /* cross-domain */

      var popup = window.open(
        'http://localhost/messageChannelPage2a.html',
        'popup',
        'toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=600,height=1100,top=0, left=1250'
      )
      popup.focus()

      popup.postMessage(
        JSON.stringify({
          message: 'myMessage',
          location: window.location.href
        }),
        //"*"
        'http://localhost/messageChannelPage2a.html'
      )

      window.addEventListener(
        'message',
        event => {
          //if (event.origin !== "./messageChannelPage1a.html") return;
          console.log(event.source, event.data)

          if (event.data === 'page-ready') {
            console.log('page-ready!!')
          } else {
            // console.log(event.source, event.data);
          }
        },
        false
      )

      /* Same origin */

      /*
      var popup = window.open(
        'http://localhost/messageChannelPage2a.html',
        'popup',
        'toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=600,height=1100,top=0, left=1250'
      )
      popup.focus()

      function postMessage() {
        popup.postMessage(
          JSON.stringify({
            message: 'myMessage',
            location: window.location.href
          }) //,
          //"http://localhost/messageChannelPage2a.html" //window.location.href //"http://localhost/messageChannelPage1a.html");
        )
      }

      window.addEventListener(
        'message',
        event => {
          //if (event.origin !== "./messageChannelPage1a.html") return;
          console.log(event.source, event.data)
          if (event.data === 'page-ready') {
            console.log('asdfasdf')
            postMessage()
          }
        },
        false
      )
        */
    </script>
  </body>
</html>



<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width" />
    <title>messageChannelPage2a.html</title>
  </head>
  <body>
    <p>messageChannelPage2a.html</p>

    <input type="text" ___value="myValue" name="input2" id="input2" />

    <script>
      window.addEventListener('message', event => {
        // if (event.origin !== "./messageChannelPage1a.html") return;
        const data = JSON.parse(event.data)

        const datum = new Date()
        console.log(datum)
        console.log(
          document.querySelector('#input2').value,
          data.message + ' ' + data.location
        )

        document.querySelector('#input2').value =
          data.message + ' ' + data.location
        const input = document.createElement('input')
        input.id = 'input3'
        input.value = data.message
        document.querySelector('body').appendChild(input)

        event.source.postMessage(
          'Message von Page 2' +
            //event.source.window.location.href +
            ' ' +
            data.message +
            ' ' +
            data.location,
          event.origin
        )
      })

      window.opener.postMessage('page-ready') // funktioniert nicht bei cross-domain
    
    </script>
  </body>
</html>
 
Was funktioniert denn jetzt genau nicht?
Ich habe inzwischen zwei Testdateien mit deinem Code gemacht. Erstes Problem: Der Browser (in meinem Fall Opera) öffnet das neue Fenster nur nach Interaktion durch den Benutzer. Führe ich einen Button ein, der das Öffnen triggert, funktioniert alles.
 
Geplant ist, dass bei Klick auf ein Icon in der Browserleiste Javascript-Code in die Internetseite injiziert wird, die gerade den Focus im Browser hat (z. B. tutorials.de). Mit diesem Code sollen dann bestimmte Daten wie z. B. Titel und URL kopiert und via postMessage an meine Localhost-Seite gesendet werden, um sie von dort aus weiter zu verarbeiten, z. B. in einer Datenbank zu erfassen. Problem ist, dass die Daten im Moment zwar in der Localhost-Seite ankommen, aber direkt wieder verschwinden.
 
Nachdem ich einen Timer eingebaut habe, klappt es im Moment so, wie ich es mir gestellt habe. Wenn du also den folgende Code über die Konsole in Tutorials.de injiziert, öffnet sich ein Window mit den Werten, mit denen man dann weiterarbeiten kann.

Für die Konsole zum Testen:
Javascript:
      ;(() => {
        var popup = window.open(
          'http://localhost/messageChannelPage2a.html',
          'popup',
          'toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=600,height=1100,top=0, left=1250'
        )
        popup.focus()

        setTimeout(()=> {
        popup.postMessage(
          JSON.stringify({
            message: 'myMessage',
            location: window.location.href
          }),
          //"*"
          'http://localhost/messageChannelPage2a.html'
        )
          },1000)

        window.addEventListener(
          'message',
          event => {
            //if (event.origin !== "./messageChannelPage1a.html") return;
            console.log(event.source, event.data)

            if (event.data === 'page-ready') {
              console.log('page-ready!!')
            } else {
              // console.log(event.source, event.data);
            }
          },
          false
        )
      })()

Code aufgerufener File:
HTML:
<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width" />
    <title>messageChannelPage2a.html</title>
  </head>
  <body>
    <p>messageChannelPage2a.html</p>

    <input type="text" ___value="myValue" name="input2" id="input2" />

    <script>
      window.addEventListener('message', event => {
        // if (event.origin !== "./messageChannelPage1a.html") return;
        const data = JSON.parse(event.data)

        const datum = new Date()
        console.log(datum)
        console.log(
          document.querySelector('#input2').value,
          data.message + ' ' + data.location
        )

        document.querySelector('#input2').value =
          data.message + ' ' + data.location
        const input = document.createElement('input')
        input.id = 'input3'
        input.value = data.message
        document.querySelector('body').appendChild(input)

        event.source.postMessage(
          'Message von Page 2' +
            //event.source.window.location.href +
            ' ' +
            data.message +
            ' ' +
            data.location,
          event.origin
        )
      })

      window.opener.postMessage('page-ready') // funktioniert nicht bei cross-domain
      
    </script>
  </body>
</html>

Funktioniert so auch mit Opera und Chrome, ggf. Popups in den Browsereinstellungen erlauben.
 
Zurück