Page loading
Skip to main content

Iframes

You can get a long way with just multiple-choice buttons! But you can build any other kind of interactives with TigYog’s iframe block (BETA!). For example, you could build:

🧾 Code editors and code runners (see example)

📈 Charts and visualizations

♟️ Interactive chess boards

🎼 Musical staves

Hello world

To begin, in the TigYog editor, add an “iframe” block. The most important thing an iframe block has is a URL. Set your iframe’s URL to:

https://tigyog-iframe-example-helloworld.glitch.me/

Then view your TigYog page in draft mode. You will see the above webpage embedded as an iframe, like this:

Notice that the iframe takes up the full page width. This is deliberate: you can use this to make, say, a full-width chart.

(Note you can fork this example iframe on Glitch. You can fork any Glitch examples in this page by going to https://glitch.com/edit/#!/ followed by the name of the example.)

Resizable iframes

The iframe has a default height of 200px. But you probably want the iframe to have the same height as your page content. You can do this using

const resizeObserver = new ResizeObserver(() => {
  window.parent.postMessage(
    {
      type: "resize",
      heightPx: document.body.scrollHeight
    },
    "https://tigyog.app"  // or "*"
  );
});
resizeObserver.observe(document.body);

Here’s a demo iframe that uses this logic to auto-resize:

https://tigyog-iframe-example-autoresize.glitch.me/

Initialization data

Let’s say you’re building a course about WebGL shaders, and you build a cool iframe that renders the shader in a canvas. Here’s a demo:

https://tigyog-iframe-example-webgl-editor.glitch.me/

Above, you can move the mouse around in the square on the left, and it will change the image. This behavior is controlled by the program on the right, which is a “shader”. You can edit the program, and it changes how the square on the left behaves.

Pretty cool! But you want to have a lot of examples like this throughout your course, and you don’t want to create a different webpage for each different example. The solution is initialization data. In the TigYog editor, this is everything in the textarea just below the iframe URL.

Try adding the above WebGL iframe to your TigYog page, but set its initialization data to:

uniform mediump vec2 mouse_pos;
void main(void) {
  gl_FragColor=vec4(
    mouse_pos.x/200.,
    mouse_pos.y/200.,
    0., 1.
  );
}

The above string is a different shader program, which makes the square behave differently. Here’s a live demo:

The init data is passed to the iframe in the fragment (hash) part of the URL. You can get the initData with:

const config = JSON.parse(
  decodeURIComponent(
    window.location.hash.slice(1)
  )
);

const initData = config.initData;

Setting the width of the iframe content

All blocks in TigYog are full-width, including iframes. To make your iframe content flush with the normal content width, apply these CSS rules:

:root {
  font-size: calc(1rem + 0.25vw);
}
body {
  margin: 0;
}
main {
  max-width: 36rem; margin: 0 auto;
}

Future feature: “I’m completed” 🔮

If you want to use an iframe for a solvable puzzle, you can add buttons immediately after the iframe. It could just be a single “Continue” button. Or it could be a set of buttons, where the reader has to use your iframe to figure out the answer.

In the future, iframes will be able to act like a button block themselves: the TigYog page content will stop at the iframe until the reader completes the task in the iframe. The iframe will be able to say “I’m completed” to the parent TigYog page.

Future feature: saving state 🔮

Say you’ve built your shader code editor iframe, like the one above. But you want each iframe in the page to save the user’s work, so it’s the same if they refresh or re-open the TigYog course, or even open the course on a different device.

Right now, you can save your iframe’s state in local storage, but this has problems: multiple iframes can clobber each other’s storage, and it’s limited to one device.

I plan to allow the iframe to save its state with something like:

window.parent.postMessage(
  {
    type: "saveState",
    state: string
  },
  "https://tigyog.app"  // or "*"
);

The state will then be provided alongside the init data.

Future feature: importable TigYog library 🔮

I plan to bundle the above JavaScript into a library/package that you can use like so:

<script src="https://tigyog.app/static/iframe.js"></script>

In the meantime, please copy-paste the JS examples from this page!

Future feature: CSS for TigYog theme 🔮

You may want your iframe to feel like a native TigYog component, matching the layout, fonts, colors, etc. Soon you’ll be able to include something like:

<link rel="stylesheet" type="text/css"
  href="https://tigyog.app/static/theme.css" />

This will give you CSS classes to apply to your components to give them the TigYog theme.

In the meantime, feel free to copy TigYog’s CSS into your webpage.

Quoted text:

Your feedback will be sent privately to the author. They may reply to you by email. Thanks for helping make this course better!