diff --git a/extensions/iframe.js b/extensions/iframe.js index 68375ea344..e39a89af4d 100644 --- a/extensions/iframe.js +++ b/extensions/iframe.js @@ -53,6 +53,8 @@ let height = -1; // negative means default let interactive = true; let resizeBehavior = "scale"; + /** @type {string|number|boolean} */ + let latestMessage = ""; const updateFrameAttributes = () => { if (!iframe) { @@ -121,6 +123,18 @@ } }; + window.addEventListener("message", (e) => { + if (iframe && iframe.contentWindow && e.source === iframe.contentWindow) { + latestMessage = + typeof e.data === "string" || + typeof e.data === "number" || + typeof e.data === "boolean" + ? e.data + : JSON.stringify(e.data); + Scratch.vm.runtime.startHats("iframe_whenMessage"); + } + }); + Scratch.vm.on("STAGE_SIZE_CHANGED", updateFrameAttributes); Scratch.vm.runtime.on("RUNTIME_DISPOSED", closeFrame); @@ -247,6 +261,29 @@ }, }, }, + "---", + { + opcode: "sendMessage", + blockType: Scratch.BlockType.COMMAND, + text: Scratch.translate("send message [MESSAGE] to iframe"), + arguments: { + MESSAGE: { + type: Scratch.ArgumentType.STRING, + defaultValue: "hello", + }, + }, + }, + { + opcode: "whenMessage", + blockType: Scratch.BlockType.EVENT, + text: Scratch.translate("when message received from iframe"), + isEdgeActivated: false, + }, + { + opcode: "iframeMessage", + blockType: Scratch.BlockType.REPORTER, + text: Scratch.translate("iframe message"), + }, ], menus: { getMenu: { @@ -379,6 +416,16 @@ } } } + + sendMessage({ MESSAGE }) { + if (iframe && iframe.contentWindow) { + iframe.contentWindow.postMessage(MESSAGE, "*"); + } + } + + iframeMessage() { + return latestMessage; + } } Scratch.extensions.register(new IframeExtension()); diff --git a/website/hello.html b/website/hello.html index 5bd51d8c8f..a86b63ae62 100644 --- a/website/hello.html +++ b/website/hello.html @@ -32,18 +32,31 @@

It works!

-

Transparency is supported, so you can display the project behind the frame as long as the page doesn't explicitly set a background color.

-

You can also use JavaScript and most other Web APIs, like this:

+

Transparent backgrounds are supported, and JavaScript works.

-

Due to browser security measures, blocks like "mouse x" and "mouse down?" will not work while the cursor is over the frame unless you use the disable interactivity block.

-

Many websites also block other sites from embedding them for security reasons.

+

You can send messages between the extension and the iframe. Try sending this iframe a message.

+ +

+

Many websites block other sites from embedding them for security reasons. Blocks like "mouse x" and "mouse down?" will not work while the cursor is over the frame unless you use the disable interactivity block.