iframe onload event difficulty

Hi everyone,

I'm trying to automatically get data from a weather API. I figured this would work:

    window.myFunction = function() {
      var weather = document.getElementById("weather").value;


<iframe  id="weather" src="https://api.openweathermap.org/data/2.5/forecast?q=Chiayi%20City,%20TW&cnt=1&appid={ImNotSupposedToShareMyID}" width="100%" height="180" style="border:0" onload="myFunction()"></iframe>

But when the iframe loads, nothing happens.

Any takers?

Thanks!


I think I found it:

var weather = document.getElementById("weather").contentWindow.document.body.innerHTML;


This only works in the Squiffy editor. Not in browsers. I don't know why.


I think it's because your game page and the iframe come from two different sources.

Something about a Same Origin Policy (I think).

https://javascript.info/cross-window-communication


In the Squiffy editor, your game is running on your own virtual server. Online, though, the game is running from this site.

It's a little confusing, and I don't understand it well enough to explain what I (think I) know about it without possibly misinforming anyone.


Thanks, K.V., I see. I guess what I'm trying to do is a security risk browsers don't want to allow.


Why are you opening it in an iframe? That seems really bizarre.

I think you want:

    $.ajax('https://api.openweathermap.org/data/2.5/forecast?q=Chiayi%20City,%20TW&cnt=1&appid={ImNotSupposedToShareMyID}', {complete: xhr => {
        var weather = xhr.responseXML;
        // do stuff here
    }});

That requests a document, and calls a function when it is completed. It doesn't display the weather page on the screen, but if you want to do that there's nothing to stop you doing:

        document.getElementById("weather").contentWindow.document.body.innerHTML = weather;

Thank you, mrangel.

I couldn't tell you the difference between bizzare javascript and the Javanese script of a fortune-teller at the bazaar. It's all just magic spells to me. On the rare ocassion one of the spells works, I am overcome with awe.

I've never even heard of $.ajax before. That even sounds like a magic word. I daftly pasted your snippet into Squiffy verbatim. Oh, oh, but I did remember to use my ID key, and felt very clever about that. Of course it didn't do anything, because I was supposed to catch your drift. Instead, I fell backward watching it fly over my head.

However, while examining the scrolls of the ancient sages at w3schools.com, I found this:

Access Across Domains
For security reasons, modern browsers do not allow access across domains. This means that both the web page and the XML file it tries to load, must be located on the same server. The examples on W3Schools all open XML files located on the W3Schools domain. If you want to use the example above on one of your own web pages, the XML files you load must be located on your own server.

I suppose, then, K.V.'s point remains.


I was just guessing, really.

If it works in the editor but not online, that usually means it's related to the site origin when using Quest.

Plus, mrangel knows much more about this stuff than I do.


Also (mainly so mrangel can see this), this is the weather page when testing with a proper API key in the url:

{"cod":"200","message":0,"cnt":1,"list":[{"dt":1629774000,"main":{"temp":304.8,"feels_like":309.42,"temp_min":304.8,"temp_max":306.43,"pressure":1009,"sea_level":1009,"grnd_level":1005,"humidity":60,"temp_kf":-1.63},"weather":[{"id":500,"main":"Rain","description":"light rain","icon":"10d"}],"clouds":{"all":87},"wind":{"speed":3.48,"deg":226,"gust":4.04},"visibility":10000,"pop":0.62,"rain":{"3h":0.16},"sys":{"pod":"d"},"dt_txt":"2021-08-24 03:00:00"}],"city":{"id":1678836,"name":"Chiayi City","coord":{"lat":23.4792,"lon":120.4489},"country":"TW","population":1000,"timezone":28800,"sunrise":1629754650,"sunset":1629800652}}

Also also, I tried mrangel's suggestion with a proper API key, but weather was undefined.

I know nothing about AJAX, though. So, it's most assuredly my fault. :o)


Trying to get at the data using the DOM in the iFrame returns this: Uncaught DOMException: Permission denied to access property "document" on cross-origin object


I've never even heard of $.ajax before. That even sounds like a magic word.

AJAX stands for Asynchronous Javascript And Xml. Basically, it means using javascript to request data from some other server. A few years ago it was like a magic word to many people, it was the special voodoo glue that was going to hold "Web 2.0" together.

Your original code attempted to get a webpage from another server, display it in an iframe, and then set a JS variable weather to the contents of the iframe.
The script I gave you should (now I fixed a silly error) get a webpage from another server and put it in a JS variable called weather. The user won't see anything because the iframe isn't there, so you'd need to do something with that variable.

But now I know that the data on that page is JSON, there's probably a better way to do it (see below):


Also also, I tried mrangel's suggestion with a proper API key, but weather was undefined.

My bad. I put innerXML instead of responseXML.

The $.ajax method basically makes an HTTP(S) request, and when the request completes it runs a callback function whose first parameter is an XMLHttpRequest object. The most usual thing to do with this is look at the responseXML or responseText properties (I assumed it would be HTML, as you were displaying it in an iframe), and the getResponseHeader method.

An alternative way is to use the XMLHttpRequest returned by $.ajax or $.get and set handlers on it directly. For example:

    $.get ("https://some.url.here/").done(
        function (data, status, xhr) {
            // 'data' is the data returned by the server
            // with JSON data, it should already be parsed for you
            // so you could set a Squiffy attribute by doing something like:
            squiffy.set("weather", "the temperature is " + data.list[0].main.temp)
        }
    ).fail(
        function (data, status, xhr) {
            squiffy.set("weather", "The weather lookup failed because " + status);
        }
    );

Now… the security thing. As KV said, most security policies won't allow access to a page from a different domain.
However, this is a public API which is specifically designed to be accessed from other applications. Therefore it will probably supply an Access-Control-Allow-Origin: header to relax these restrictions.

You might need to tell that site somewhere on your account page which domains you will be accessing it from; some APIs require you to provide this information to ensure that the app using your key is really yours. So you'd need to give them the domain name of the site that's hosting the game. On this site, it would be media.textadventures.co.uk.

However, there may still be some odd and unpredictable issues if your game is hosted on HTTP. If you're hosting on this site, check that the address in your browser starts with https:// and not http://.


That works!

Thanks, mrangel! You the man!


This... is.... AMAZING! It works like magic! Thank you, mrangel! No more spending ten minutes every morning looking up the weather, deciding how to phrase it in simple English, and then having it be inaccurate for my later classes!


This topic is now closed. Topics are closed after 180 days of inactivity.

Support

Forums