Skip to content

Commit

Permalink
Readme updates
Browse files Browse the repository at this point in the history
  • Loading branch information
jakiestfu committed Aug 27, 2016
1 parent 2455dc5 commit 270052c
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 18 deletions.
4 changes: 2 additions & 2 deletions Gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ const serveStatic = require('serve-static');
const source = require('vinyl-source-stream');
const uglify = require('rollup-plugin-uglify');

var parentServer
var childServer;
var parentServer; // eslint-disable-line no-var
var childServer; // eslint-disable-line no-var

const pkg = require('./package.json');
const banner = ['/**',
Expand Down
75 changes: 59 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,26 +26,33 @@ You can download the compiled javascript directly [here](/build/postmate.min.js)

## Features
* Promise based API for elegant and simple communication
* Secure. Two way parent <-> child handshake, with origin and message validation.
* Child can expose properties, functions, or promises that the parent can retrieve.
* Secure. Two way parent <-> child handshake, with message validation.
* Child exposes a `model`, an object literal whose values consist of serializable values, functions and promises, that the parent can retrieve.
* Child can emit events that the parent can listen to.
* *Zero* dependencies. Provide your own polyfill or abstraction for the `Promise` API if needed
* Lightweight, weighing in at ~ `3kb`

## Installing
Postmate can be installed via NPM or Bower.

**NPM**
```bash
$ npm i postmate # Install via NPM
# or
```

**bower**
```bash
$ bower i postmate # Install via Bower
```

## Glossary
* **`Parent`**: The **top level** page that will embed an `iFrame`, creating a `Child`
* **`Child`**: The **bottom level** page that exposes information to the `Parent`. This is the `iFrame`s `src`
* **`Child`**: The **bottom level** page loaded within the `iFrame`
* **`Model`**: The object that the `Child` exposes to the `Parent`

## Usage
1. The `Parent` begins communication with the `Child`. A handshake is sent, the `Child` responds with
a handshake reply, finishing `Parent` initialization. The two are bound and ready to communicate.
a handshake reply, finishing `Parent`/`Child` initialization. The two are bound and ready to communicate securely.

2. The `Parent` fetches values from the `Child` by property name. The `Child` can emit messages to the parent.

Expand All @@ -65,32 +72,49 @@ handshake.then(child => {
// Fetch the height property in child.html and set it to the iFrames height
child.get('height')
.then(height => child.frame.style.height = `${height}px`);

// Listen to a particular event from the child
child.on('some-event', data => console.log(data)); // Logs "Hello, World!"
});
```

**child.com/page.html**
```javascript
new Postmate.Model({
const handshake = new Postmate.Model({
// Expose your model to the Parent. Property values may be functions, promises, or regular values
height: () => document.height || document.body.offsetHeight
});

// When parent <-> child handshake is complete, events may be emitted to the parent
handshake.then(parent => {
parent.emit('some-event', 'Hello, World!');
});
```

***

## API

> ## `Postmate.debug`
```javascript
// parent.com or child.com
Postmate.debug = true;
new Postmate(options);
```

Name | Type | Description | Default
:--- | :--- | :--- | :---
`debug` | `Boolean` | _Set to `true` to enable logging of additional information_ | `undefined`

***

> ## `Postmate(options)`
```javascript
// parent.com
new Postmate({
container: document.body,
url: 'http://child.com/'
url: 'http://child.com/',
model: { foo: 'bar' }
});
```
> This is written in the parent page. Initiates a connection with the child. Returns a Promise that signals when the handshake is complete and communication is ready to begin.
Expand All @@ -103,65 +127,69 @@ Name | Type | Description | Default
:--- | :--- | :--- | :---
**`container`** (optional) | `DOM Node Element` | _An element to append the iFrame to_ | `document.body`
**`url`** | `String` | _A URL to load in the iFrame. The origin of this URL will also be used for securing message transport_
**`model`** | `Object` | _An object literal to represent the default values of the Childs model_

***

> ## `Postmate.Model(model)`

> ```javascript
// child.com
new Postmate.Model({
// Serializable values
foo: "bar",
>
// Functions
height: () => document.height || document.body.offsetHeight,
>
// Properties
foo: "bar",
>
// Promises
data: fetch(new Request('data.json'))
});
```
> This is authored in the child page. Attaches Message Event listeners for a handshake. Once handshake is accepted, an event listener is bound to receive requests from the Parent.
> This is written in the child page. Calling `Postmate.Model` initiates a handshake request listener from the `Parent`. Once the handshake is complete, an event listener is bound to receive requests from the `Parent`. The `Child` model is _extended_ from the `model` provided by the `Parent`.
#### Parameters

Name | Type | Description
Name | Type | Description | Default
:--- | :--- | :---
**`model`** | `Object` | _An object of gettable properties to expose to the parent. Value types may be anything accepted in `postMessage`. Promises may also be set as values or returned from functions._
**`model`** | `Object` | _An object of gettable properties to expose to the parent. Value types may be anything accepted in `postMessage`. Promises may also be set as values or returned from functions._ | `{}`

***

> ## `child.get(key)`
```javascript
// parent.com
new Postmate({
container: document.body,
url: 'http://child.com/'
}).then(child => {
child.get('something').then(value => console.log(value));
});
```
> Retrieves a value by property from the Childs `model` object.
> Retrieves a value by property name from the `Childs` `model` object.
**Returns**: Promise(value)

#### Parameters

Name | Type | Description
:--- | :--- | :---
**`key`** | `String` | _The string property to lookup in the childs `model`_
**`key`** | `String` (required) | _The string property to lookup in the childs `model`_

***

> ## `child.destroy()`
```javascript
// parent.com
new Postmate({
container: document.body,
url: 'http://child.com/'
}).then(child => child.destroy());
```
> Removes the `iFrame` element and destroys any `message` event listeners
**Returns**: Promise(value)
**Returns**: `undefined`

***

Expand All @@ -175,12 +203,27 @@ new Postmate(options).then(child => {
> The iFrame Element that the parent is communicating with
## Troubleshooting

### Silent Parent/Child
#### I've enabled logging but the parent or child is not logging everything.
> _Postmate.debug needs to be set in both the parent and child for each of them to log their respective information_
#### The child does not respond to communication from the Parent
> _Make sure that you have initialized Postmate.Model in your child page._
### Restrictive Communication
#### I want to retrieve information from the parent by the child
> _Postmate (by design) is restrictive in its modes of communication. This enforces a simplistic approach: The parent is responsible for logic contained within the parent, and the child is responsible for logic contained within the child. If you need to retrieve information from parent -> child, consider setting a default `model` in the parent that the child may extend._
#### I want to send messages to the child from the parent
> _The parent cannot send messages. However, a simple request to a function in the child via `child.get` is possible, and can solve most scenarios, but is advised against._
### Security
#### What is the Handshake and why do I need one?
> _By default, all `message` events received by any (parent) page can come from any (child) location. This means that the `Parent` must always enforce security within its message event, ensuring that the `child` (origin) is who we expect them to be, that the message is a response from an original request, and that our message is valid. The handshake routine solves this by savind the identities of the child and parent and ensuring that no changes are made to either._
#### How are messages validated?
> _The origin of the request, the message type, the postMessage mime-type, and in some cases the message response, are all verified against the original data made when the handshake was completed. _
## License
MIT

0 comments on commit 270052c

Please sign in to comment.