Iframes
In this tutorial you'll learn how to use the iframe
VM tag and the Iframe resizer library, so you can embed external HTML or use custom DOM elements when building NEAR components.
You can use it along the rest of approved VM tags to simplify your component development.
Using IFrames on NEAR VM
Iframes can be used to embed external HTML or to use custom DOM
elements, for example canvas
.
Properties
The iframe
tag takes the following properties: className
, style
, src
,
srcDoc
, title
, message
, and onMessage
. The iframe has a sandbox property
set to sandbox="allow-scripts"
, which only allows scripts.
message
and onMessage
are used to communicate with this iframe
instance.
param | description |
---|---|
message | it's passed to the iframe every time the deep equal is different, or the iframe is recreated. The message is passed using contentWindow.postMessage(message, "*") on the iframe. |
onMessage(data) | it's called when the iframe passes a message to window.top . Only event.data is passed to the onMessage |
Events
The VM exposes the following <iframe>
events:
-
onLoad()
: support foronLoad
event without any event info<iframe onLoad={() => { console.log('iframe loaded') }}>
-
onResized()
: support foronResized
Iframe Resizer event with an object only containing the newwidth
andheight
<iframe iframeResizer={{
onResized: ({width, height}) => { console.log('iframe resized', width, height) },
}}>
Example
The following example demonstrates how you can use an iframe to call
eval
:
State.init({
text: `"b" + "a" + +"a" + "a"`,
});
const code = `
<div>Expression: <pre id="exp" /></div>
<div>Results: <pre id="res" /></div>
<script>
window.top.postMessage("loaded", "*");
window.addEventListener("message", (event) => {
const data = event.data
document.getElementById("exp").innerHTML = JSON.stringify(data);
try {
const result = eval(data.exp);
document.getElementById("res").innerHTML = result;
event.source.postMessage(result, "*");
} catch (e) {
// ignore
}
}, false);
</script>
`;
return (
<div>
<input
value={state.text || ""}
onChange={(e) => State.update({ text: e.target.value })}
/>
Iframes below
<div className="d-flex">
<iframe
className="w-50 border"
srcDoc={code}
message={{ exp: state.text || "" }}
onMessage={(res1) => State.update({ res1 })}
/>
<iframe
className="w-50 border"
srcDoc={code}
message={{ exp: (state.text || "") + " + ' banana'" }}
onMessage={(res2) => State.update({ res2 })}
/>
</div>
Result:{" "}
<pre>
res1 = {JSON.stringify(state.res1)}
res2 = {JSON.stringify(state.res2)}
</pre>
</div>
);
Iframe Resizer
Iframe Resizer is a critical library for rendering responsive iframes. This library automatically resizes the iframe
to match the child content size to avoid scrollbars on the iframe
itself.
The child page rendered by the iframe
must include this script in order for the resizing to work:
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/4.3.6/iframeResizer.contentWindow.js"></script>
NEAR VM uses the React flavor of this plugin.
Basic Example
You can use the Iframe resizer library like this:
return (
<div>
<iframe
iframeResizer
src="https://davidjbradshaw.com/iframe-resizer/example/frame.content.html"
/>
</div>
);
If you need to pass in options to override the default behavior:
return (
<div>
<iframe
iframeResizer={{ log: true }}
src="https://davidjbradshaw.com/iframe-resizer/example/frame.content.html"
/>
</div>
);
You can check this example to see a complete component using Iframe Resizer.
srcDoc
Example
An example of a valid srcDoc
for a secure Iframe using iframeResizer
:
const code = `
<script>
// ...your code...
// define message handler
const handleMessage = (m) => {
console.log('received message', m)
document.getElementById("messageText").innerHTML = m;
};
// finally, configure iframe resizer options before importing the script
window.iFrameResizer = {
onMessage: handleMessage
}
</script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/4.3.6/iframeResizer.contentWindow.js"></script>
<p id="messageText">loading...</p>
`;
return (
<div>
<iframe
iframeResizer
className="w-100"
srcDoc={code}
message="my message"
/>
</div>
);