npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

paired-frame

v2.0.0

Published

Helper library for cross-frame communication

Downloads

208

Readme

PairedFrame

A cross-frame communication library

PairedFrame is a utility for when you have no choice but to embed part of your site in an iframe. It allows you to:

  • Avoid scrollbars, clipping, and loading FOUC
  • Synchronize SPA navigation
  • Proxy modals and toast messages to the parent window
  • Send arbitary messages between frames

Iframes impact both security and performance. PairedFrame does what it can to provide a seamless integration without making these problems worse.

Tour

Each PairedFrame instance acts as a stand-in for an iframe or parent frame.

const parent = new PairedFrame({
  targetWindow: window.parent,
  targetOrigin: 'https://child.loc:3000',
  ...options
});

PairedFrame is a Node-style event emitter.

parent.once('ready', () => {
  myIframeElement.style.opacity = 1;
});

parent.on('heartbeat', console.log);

parent.emit('some-event-name', someEventData);

You can also send arbitrary messages to the counterpart frame, which will be emitted as events there.

parent.send('some-event-name', someEventData);

The class includes some low-level, promise-based methods to proxy interactive experiences (such as modal windows) from a child frame to a parent frame.

const confirmed = await parent.dialog({ type: 'modal', text: 'Are you sure?' });

Options

The PairedFrame constructor accepts a dictionary of options:

targetOrigin

Required

The origin of the frame being targeted, including protocol, hostname, and port (if different than the default expected for the protocol). Only messages hailing from a counterpart at this origin will be trusted.

targetWindow

Required

A reference to the counterpart's window. When connecting from a host frame to an iframe, this is the iframe element's contentWindow. When connecting from an iframe to its host, this is window.parent.

sendHeight

Boolean. If true, the local scrollHeight will be monitored and broadcast to the counterpart. This should be enabled for the child frame to enable automatic height syncing.

autoResize

Boolean. If true, the height of resizeElement will be automatically updated to match the scrollHeight of the counterpart frame. This should be enabled for the parent frame to enable automatic height syncing.

resizeElement

Required if autoResize is true

A reference to the element that should be resized to match the counterpart's scrollHeight. For best performance, this should be a wrapper div around the iframe with overflow set to "hidden". The iframe itself should have a static height large enough to accommodate the maximum height of its content.

If your iframe's maximum content height is not predictable (for example, if it has infinitely scrolling content), you can also pass a reference to the iframe element itself. This will work, but may degrade performance during animations.

sendHistory

Boolean. If true, the local pathname will be monitored and broadcast to the counterpart. This should be enabled for both frames to enable automatic navigation syncing.

autoNavigate

Boolean. If true, the local pathname will be automatically updated (using history.replaceState) in response to pathname changes in the counterpart. Then a synthetic popstate event (which typically represents browser navigation) is fired to trigger any active routing library to examine the new pathname and, if necessary, render a new state.

translatePath

(remotePath, requestedPath) => localPath

Function. If provided, will be used to convert the counterpart's new pathname into the equivalent local pathname. This allows the parent and child frames to have uniquely named routes that can still be mapped to each other.

providePath

(localPath) => remotePath

Function. If provided, will be used to translate new local pathnames into the requestedPath argument that will be fed to the counterpart's translatePath. The counterpart may optionally defer to requestedPath rather than deriving a path from remotePath. This allows one frame to manage route syncing for both frames.

Methods

dialog(config)

Notifies the counterpart to initiate some kind of interactive dialog. Returns a promise that will be resolved with the result of that dialog.

PairedFrame only manages communication of the dialog state; it is up to the user to implement the actual modal, toast message, etc. To that end, config can be structured however you like.

onDialog(callback)

A special handler for accepting and responding to dialog requests. callback will receive the dialog config as its first argument and should return a promise that resolves with the result of the interaction. Returns the PairedFrame instance for chaining.

on(eventName, callback)

Registers a callback to fire for the given event. Returns the PairedFrame instance for chaining.

once(eventName, callback)

Registers a callback to fire once for the given event, then deregister itself. Returns the PairedFrame instance for chaining.

off(eventName, callback)

Deregisters a callback for the given event. Returns the PairedFrame instance for chaining.

emit(eventName, data)

Emits an event in the local frame, firing any registered callbacks. Returns the number of callbacks that were fired in response.

send(eventName, data)

Emits an event in the counterpart frame, firing any registered callbacks. This can be used to send arbitrary messages between frames. Returns true.

eventNames()

Returns an array of all event names that currently have registered callbacks.

listeners(eventName)

Returns an array of callbacks currently registered for the given event.

listenerCount(eventName)

Returns the number of callbacks currently registered for the given event.

destroy()

Removes the postMessage listener. Any callbacks attached to the "destroy" event will be fired, after which no callbacks will be fired or postMessages sent.

Built-in events

  • load: Indicates that both frames have loaded, but the connection has not yet been set up.
  • ping: Indicates that the counterpart wishes to establish a connection.
  • pong: Indicates that the counterpart has approved the connection.
  • ready: Indicates that both frames are ready to communicate.
  • postmessage-sent: Indicates that a postMessage has been sent to the counterpart.
  • postmessage-received: Indicates that a postMessage has been received from the counterpart.
  • resize: Indicates that the counterpart's scrollHeight has changed.
  • height-updated: Indicates that the local frame's height has been auto-updated in response to a resize event.
  • navigate: Indicates that the counterpart's pathname has changed.
  • path-updated: Indicates that the local frame's path has been auto-updated in response to a navigate event.
  • dialog-opened: Indicates that a dialog has been requested (by either frame).
  • dialog-closed: Indicates that a dialog has been resolved (by either frame).
  • heartbeat: Sent every 250ms by each frame to monitor connection.
  • connection-lost: Indicates that 500ms have passed without a counterpart heartbeat event.
  • connection-restored: Indicates that a counterpart heartbeat event has been received following a lost connection.
  • destroy: Fired just before the instance removes its postMessage handler and stops sending or responding to events.
  • *: All events. Can be used for logging.

Running the demo

  1. Add parent.loc and child.loc to /etc/hosts pointing at 127.0.0.1
  2. Run yarn demo
  3. Navigate to http://parent.loc:3000 in your browser