Skip to content

Commit 615b6c4

Browse files
authored
iframe: add message blocks (TurboWarp#2250)
1 parent 5973c35 commit 615b6c4

2 files changed

Lines changed: 65 additions & 5 deletions

File tree

‎extensions/iframe.js‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@
5353
let height = -1; // negative means default
5454
let interactive = true;
5555
let resizeBehavior = "scale";
56+
/** @type {string|number|boolean} */
57+
let latestMessage = "";
5658

5759
const updateFrameAttributes = () => {
5860
if (!iframe) {
@@ -121,6 +123,18 @@
121123
}
122124
};
123125

126+
window.addEventListener("message", (e) => {
127+
if (iframe && iframe.contentWindow && e.source === iframe.contentWindow) {
128+
latestMessage =
129+
typeof e.data === "string" ||
130+
typeof e.data === "number" ||
131+
typeof e.data === "boolean"
132+
? e.data
133+
: JSON.stringify(e.data);
134+
Scratch.vm.runtime.startHats("iframe_whenMessage");
135+
}
136+
});
137+
124138
Scratch.vm.on("STAGE_SIZE_CHANGED", updateFrameAttributes);
125139

126140
Scratch.vm.runtime.on("RUNTIME_DISPOSED", closeFrame);
@@ -247,6 +261,29 @@
247261
},
248262
},
249263
},
264+
"---",
265+
{
266+
opcode: "sendMessage",
267+
blockType: Scratch.BlockType.COMMAND,
268+
text: Scratch.translate("send message [MESSAGE] to iframe"),
269+
arguments: {
270+
MESSAGE: {
271+
type: Scratch.ArgumentType.STRING,
272+
defaultValue: "hello",
273+
},
274+
},
275+
},
276+
{
277+
opcode: "whenMessage",
278+
blockType: Scratch.BlockType.EVENT,
279+
text: Scratch.translate("when message received from iframe"),
280+
isEdgeActivated: false,
281+
},
282+
{
283+
opcode: "iframeMessage",
284+
blockType: Scratch.BlockType.REPORTER,
285+
text: Scratch.translate("iframe message"),
286+
},
250287
],
251288
menus: {
252289
getMenu: {
@@ -379,6 +416,16 @@
379416
}
380417
}
381418
}
419+
420+
sendMessage({ MESSAGE }) {
421+
if (iframe && iframe.contentWindow) {
422+
iframe.contentWindow.postMessage(MESSAGE, "*");
423+
}
424+
}
425+
426+
iframeMessage() {
427+
return latestMessage;
428+
}
382429
}
383430

384431
Scratch.extensions.register(new IframeExtension());

‎website/hello.html‎

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,31 @@
3232
<head>
3333
<main>
3434
<h1>It works!</h1>
35-
<p>Transparency is supported, so you can display the project behind the frame as long as the page doesn't explicitly set a background color.</p>
36-
<p>You can also use JavaScript and most other Web APIs, like this:</p>
35+
<p>Transparent backgrounds are supported, and JavaScript works.</p>
3736
<p><button class="clickme">Click me!</button></p>
38-
<p>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.</p>
39-
<p>Many websites also block other sites from embedding them for security reasons.</p>
37+
<p>You can send messages between the extension and the iframe. Try sending this iframe a message.</p>
38+
<input type="text" class="input" value="Hi from the iframe!"> <button class="send">Send!</button>
39+
<p class="received"></p>
40+
<p>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.</p>
4041
</main>
4142
<script>
4243
let clicks = 0;
43-
document.querySelector('.clickme').addEventListener('click', (e) => {
44+
document.querySelector(".clickme").addEventListener("click", (e) => {
4445
clicks++;
4546
e.target.textContent = `Clicks: ${clicks}`;
4647
});
48+
49+
document.querySelector(".send").addEventListener("click", (e) => {
50+
const message = document.querySelector(".input").value;
51+
document.querySelector(".input").value = "";
52+
window.parent.postMessage(message, "*");
53+
});
54+
55+
window.addEventListener("message", (e) => {
56+
if (e.source === window.parent && e.source !== window) {
57+
document.querySelector(".received").textContent = `Last message received by iframe: ${e.data}`;
58+
}
59+
});
4760
</script>
4861
</head>
4962
</html>

0 commit comments

Comments
 (0)