A simple web browser iframe host/client channel message manager. It uses MessageChannels to avoid cross-talk between multiple iframes. It allows configuring the iframe to run in sandboxed mode.
A user first initiates the creation of a client iframe using the createHost(url)
method, adding event
handlers using on(eventName, data)
. They then creates the iframe using build()
, and opens
a communication channel using connect()
. Once the channel opens, the user can send messages to
the client with send(eventName, data)
import { Chatty } from 'chatty'
Chatty.createHost('//example.com/client.html')
.on(Actions.SET_STATUS, (msg: Msg) => {
const status: Element = document.querySelector('#host-status')!
status.innerHTML = `${msg.status} 1`
})
.build()
.connect()
.then(client => {
document.querySelector('#change-status')!.addEventListener('click', () => {
client.send(Actions.SET_STATUS, { status: 'Message to client 1' })
})
})
.catch(console.error)
The client iframe can also be created using source from the createHostFromSource(source)
method.
import { Chatty } from 'chatty'
Chatty.createHostFromSource(`
<html>
<body>
<script src='//example.com/client.js' type="application/javascript" />
</body>
</html>
`)
The client iframe
creates its client using createClient()
. It also adds event listeners, builds the
client and connects. Once connected, it can send messages to its host.
import { Chatty } from 'chatty'
Chatty.createClient()
.on(Actions.SET_STATUS, (msg: Msg) => {
const status = document.querySelector('#client-status')!
status.innerHTML = msg.status
})
.build()
.connect()
.then(host => {
document.querySelector('#change-status')!.addEventListener('click', () => {
host.send(Actions.SET_STATUS, { status: 'click from client' })
})
})
.catch(console.error)
Both the host and the client can send a message and wait for a response. The sendAndReceive()
method
returns a promise that is resolved with a values returned by the event listeners on the client or host.
For example, a host can request that the client return its title.
import { Chatty } from 'chatty'
Chatty.createHost('//example.com/client.html')
.build()
.connect()
.then(client => {
document.querySelector('#get-title')!.addEventListener('click', () => {
client.sendAndReceive(Actions.GET_TITLE, (payload: any[]) => {
const title: Element = document.querySelector('#got-title')!
title.innerHTML = payload[0]
}
})
})
.catch(console.error)
The client simply returns the text value of its title in the event handler.
import { Chatty } from 'chatty'
Chatty.createClient()
.on(Actions.GET_TITLE, () => {
return document.querySelector('title')!.text
})
.build()
.connect()
.catch(console.error)
The results provided by the promise are an array because their may be multiple handlers for a given event. If there are no event handlers for a given action the array will be empty.
The sendAndReceive
method can also be used for data that needs to be retrieved asynchronously. In this scenario
the target function must return a Promise.
In the following example, the host requests that the client return some data that is to be retrieved asynchronously.
import { Chatty } from 'chatty'
Chatty.createHost('//example.com/client.html')
.build()
.connect()
.then(client => {
document.querySelector('#get-title')!.addEventListener('click', () => {
client.sendAndReceive(Actions.GET_TITLE, (payload: any[]) => {
const title: Element = document.querySelector('#got-title')!
title.innerHTML = payload[0]
}
})
})
.catch(console.error)
The client message handler returns a Promise
.
import { Chatty } from 'chatty'
Chatty.createClient()
.on(Actions.GET_TITLE, () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(document.querySelector('title')!.text)
}, 200)
})
})
.build()
.connect()
.catch(console.error)
- Make sure you have node and npm versions installed per
package.json
's "engines" field. npm install
npm test
npm start
- Happy hacking!
/src
- This is where you should do all the work on Chatty./lib
- This is the built output generated by runningnpm run build
. No editing should be done here./demo
- This is what is hosted by WebpackDevServer vianpm start
. Use this to build a demo and test Chatty in real time (no need to refresh the page manually or restart the dev server, it does that for you).
npm run build
- runs the Typescript compiler, outputting all generated source files to/lib
. Run this when creating a new build to distribute on github.npm run lint
- runs the ts linternpm run lint-fix
- runs the ts linter and attempts to auto fix problemsnpm start
- starts a dev server mounted on/demo
.npm test
- runs the test suite for Chatty.