Across Tabs
Easy communication between cross-origin browser tabs. Simplified "CORS"ing!
Install / Use
npx skills add wingify/across-tabsInstalls into whichever agent you are using.
README
<img src="https://raw.githubusercontent.com/wingify/across-tabs/master/across-tabs.png" alt="Across tabs" width="50" height="50"/> AcrossTabs - Easy communication between cross-origin browser tabs.
<a href="https://news.ycombinator.com/item?id=14041400"><img src="https://raw.githubusercontent.com/wingify/across-tabs/master/images/hn.png" width="150" height="20"/></a> <a href="https://www.producthunt.com/posts/across-tabs"><img src="https://raw.githubusercontent.com/wingify/across-tabs/master/images/product_hunt.png" width="100" height="20"/></a>
- Features
- Installation
- Flow diagram
- Usage
- API
- Browser support
- Development Stack
- Process
- Scripts
- Contributing
- Roadmap
- Authors
- Copyright and license
Features
- Safely enables cross-origin communication among different browser tabs. Uses
PostMessageAPI for communication. - Easy to hook custom callback at various levels. Eg: executing a custom method in Child's tab on receiving a message from Parent tab.
- Option to provide
data-tab-opener="name"attribute on the target link/button(which opens up a new tab), so that it remains to disable untilChildtab initiates a handshake and is received by theParenttab - Fully fledged API to get information regarding the tabs(Parent and Child tabs) and other communication-related methods.
- Exports in a UMD format i.e. library works everywhere.
- Only
~4 KBgzipped.
Installation
- Via npm
$ npm install across-tabs
- Via bower
$ bower install across-tabs
- Via cdnjs, using
<script>tag
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/across-tabs/1.0.0/across-tabs.min.js"></script>
Note: Use the desired version of the library in place of 1.0.0. Checkout cdnjs across-tabs.
Flow Diagram
- Opener/Parent tab(
P) opens up a new Child tab(C). Cinitiates a handshake with thePtab by sending apostMessage.Packnowledges the request and sendsCit's identity i.e.UUIDalong withPinformation.- This sets up a communication channel between Parent and Child tab.
- Now,
PandCcan share custom messages with each other. - Whenever
Cgets closed/refreshed,Pis notified. - Whenever
Pis closed/refreshed, all children ofPtab gets notified.
Explanation of diagram
- Parent(
P) opens Child tab(C1) att=1. c1a- WhenC1initiates a handshake with the Parent.P1- WhenPreceivesC1message.P2-Packnowledges the request and sends theC1its identity.c1b- WhenC1receives an acknowledgement message along with identity fromP.
Total Tabs Associated: 1 | Opened Tabs: 1 | Closed Tabs: 0
- Parent(
P) opens CHild tab(C2) att=10. c2a- WhenC2initiates a handshake with the Parent.P3- WhenPreceivesC2message.P4-Packnowledges the request and sends theC2its identity.c2b- WhenC2receives acknowledgemnet message along with identity fromP.
Total Tabs Associated: 2 | Opened Tabs: 2 | Closed Tabs: 0
c1c- TabC1closes.P5-Pis notified about theC1. Parent updates the list.
Total Tabs Associated: 2 | Opened Tabs: 1 | Closed Tabs: 1
- Parent(
P) opens CHild tab(C3) att=25. c3a- WhenC3initiates a handshake with the Parent.P6- WhenPreceivesC3message.c2c- TabC2sends acustommessage.P7- WhenPreceives a message from tabC2. It processes it.P8-Packnowledges the request and sends theC3its identity.c3b- WhenC3receives acknowledgemnet message along with identity fromP.
Total Tabs Associated: 3 | Opened Tabs: 2 | Closed Tabs: 1
- When Parent Tab
Pis closed, all the opened tabs are notified about it.
Usage
Create an instance / reference before using.
Opener(Parent) tab
var config = {
onHandshakeCallback: function () { ... },
onPollingCallback: function () { ... },
onChildCommunication: function () { ... }
}
var parent = new AcrossTabs.Parent(config);
Constructor accepts a configurable Object with the following keys.
heartBeatInterval: The time interval for polling tabs statusesremoveClosedTabs: Pass it astrueto have only opened tabs in the listshouldInitImmediately: Pass it asfalseto create an instance but initialize it lateronHandshakeCallback: Callback to be called when a successful connection has been establishedonChildCommunication: Callback to be called when child sends messageonPollingCallback: Callback to be called every time a tab is polled for its statusorigin: whitelistoriginfor securingpostMessagecommunication. It will discard the malicious messages trying to trick the behavior. Eg. http://example.comparse: parser used when parsing messages, defaults toJSON.parsestringify: stringifier used when converting data into messages, defaults toJSON.stringify
| Config Keys | default | accepts | | ------------------------- | -------------- | ---------------------------------- | | heartBeatInterval | 500 msec | A number representing milliseconds | | removeClosedTabs | false | Boolean | | shouldInitImmediately | true | Boolean | | onHandshakeCallback | Undefined | Function as callback | | onChildCommunication | Undefined | Function as callback | | onPollingCallback | Undefined | Function as callback | | origin | '*' | String(url) | | parse | JSON.parse | Function | | stringify | JSON.stringify | Function |
New(Child tab)
var config = {
onReady: onReady,
onInitialize: onInitialize,
isSiteInsideFrame: false, // dont set if not required
handshakeExpiryLimit: 4000, // msec
onParentDisconnect: onParentDisconnect,
onParentCommunication: onParentCommunication
};
var child = new AcrossTabs.Child(config);
Constructor accepts a configurable Object with the following keys.
handshakeExpiryLimit: Time to wait for getting an acknowledgement from Parent window for child's requestonReady: Callback to be invoked once child instance is readyonInitialize: Callback when a child instance is actually initiatedonParentDisconnect: Callback to be invoked when Parent gets disconnectedonParentCommunication: Callback to be invoked whenever Parent communicates with the child tabisSiteInsideFrame: If the library is loaded inside an iframe in the child tab, this needs to be settruefor maintaining proper window/frame(s) referencesorigin: whitelistoriginfor securingpostMessagecommunication. It will discard the malicious messages trying to trick the behavior. Eg. http://example.comparse: parser used when parsing messages, defaults toJSON.parsestringify: stringifier used when converting data into messages, defaults toJSON.stringify
| Config Keys | default | accepts | | ------------------------- | -------------- | -------------------------------------- | | handshakeExpiryLimit | 5000 msec | A number representing milliseconds | | isSiteInsideFrame | null | If child tab has actual site in a fram | | onReady | Undefined | Function as callback | | onInitialize | Undefined | Function as callback | | onParentDisconnect | Undefined | Function as callback | | onParentCommunication | Undefined | Function as callback | | origin | '*' | String(url) | | parse | JSON.parse | Function | | stringify | JSON.stringify | Function |
Example is included in the example folder. Vanilla JS and Vue js versions are there to test out.
Note: Run npm install if you wish to run vuejs example since the example needs the vue-js library to work.
API
Refer above section on how to create an instance before hitting API methods.
Opener Tab(Parent) Methods
-
openNewTabSaves `data
Related Skills
node-connect
385.6kDiagnose OpenClaw Android, iOS, or macOS node pairing, QR/setup code, route, auth, and connection failures.
blender-python-addon
40.5kBlender Python add-on rules for operators, panels, properties, registration, testing, and API-safe scripting
flutter-development-guidelines-cursorrules-prompt-file
40.5kCursor rules for Flutter development with MVVM architecture, Riverpod state management, Material widgets, and Dart style guidelines.
commit-push-pr
140.7kCommit, push, and open a PR

