Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,38 @@ To configure your playground even further, add one or more of the following attr
| data-width | number | string | '100% ' | width of the element |
| data-loading | eager | lazy | 'lazy' | load the frame eager or lazy (see iframe specs) |

#### dynamic updates

Playground can be updated using [cross-window messaging](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage)
after it has been loaded. After the playground is loaded, you can update it with following message: `{type: 'UPDATE_DATA', markup: 'new markup', query: 'new query'}` with both `markup` and `query` being optional.

To find out, if playground is ready, you can listen for a message `{source: 'embedded-testing-playground', type: 'READY'}`
in window from which are you embedding the playground.

Example:

```html
<template data-testing-playground data-class="messaging-iframe"></template>
<script type="text/javascript">
function updatePlayground() {
const iframe = document.querySelector('.messaging-iframe');
iframe.contentWindow.postMessage(
{ type: 'UPDATE_DATA', markup: 'new markup', query: 'new query' },
'https://testing-playground.com',
);
}

window.addEventListener('message', ({ data }) => {
if (
data.source === 'embedded-testing-playground' &&
data.type === 'READY'
) {
updatePlayground();
}
});
</script>
```

## Roadmap

Future ideas are maintained in [roadmap.md]. Please use the [issue tracker] to discuss any questions or suggestions you have.
Expand Down Expand Up @@ -127,6 +159,7 @@ Thanks goes to these people ([emoji key][emojis]):

<!-- markdownlint-enable -->
<!-- prettier-ignore-end -->

<!-- ALL-CONTRIBUTORS-LIST:END -->

This project follows the [all-contributors][all-contributors] specification.
Expand Down
3 changes: 3 additions & 0 deletions src/components/Embedded.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Preview from './Preview';
import Query from './Query';
import Result from './Result';
import MarkupEditor from './MarkupEditor';
import useParentMessaging from '../hooks/useParentMessaging';
import usePlayground from '../hooks/usePlayground';
import Loader from './Loader';

Expand Down Expand Up @@ -67,6 +68,8 @@ function Embedded(props) {
return () => document.body.classList.remove('embedded');
}, []);

useParentMessaging(dispatch);

return (
<div className="relative w-full h-full">
<Loader loading={isLoading} />
Expand Down
17 changes: 17 additions & 0 deletions src/embed.html
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,23 @@
</script>
</template>

<template data-testing-playground data-class="messaging-iframe"></template>
<script type="text/javascript">
function updatePlayground() {
const iframe = document.querySelector('.messaging-iframe');
iframe.contentWindow.postMessage(
{ type: 'UPDATE_DATA', markup: 'new markup', query: 'new query' },
'http://localhost:1234',
);
}

window.addEventListener('message', ({ data }) => {
if (data.source === 'embedded-testing-playground' && data.type === 'READY') {
updatePlayground();
}
});
</script>

<script async src="embed.js"></script>
</body>
</html>
50 changes: 50 additions & 0 deletions src/hooks/useParentMessaging.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { useEffect } from 'react';

function dispatchUpdateData(dispatch, { markup, query }) {
if (markup !== undefined) {
dispatch({ type: 'SET_MARKUP', markup });
}

if (query !== undefined) {
dispatch({ type: 'SET_QUERY', query });
}
}

function useParentMessaging(dispatch) {
useEffect(() => {
if (window === parent) {
return;
}

const listener = ({ source, target, data }) => {
if (source !== parent) {
return;
}

if (target !== window) {
return;
}

switch (data.type) {
case 'UPDATE_DATA':
dispatchUpdateData(dispatch, data);
break;
default:
return;
}
};

window.addEventListener('message', listener);

parent.postMessage(
{
source: 'embedded-testing-playground',
type: 'READY',
},
'*', // We don't know parent origin, so we have to send it to whoever is there
);
return () => window.removeEventListener('message', listener);
}, [dispatch]);
}

export default useParentMessaging;