flyer.js is a lightweight messaging library written for clojurescript & javascript.
It provides broadcast messaging between frames, iframes, and windows.
[flyer "1.1.2"]
flyer {:mvn/version "1.1.2"}
compile 'flyer:flyer:1.1.2'
<dependency>
<groupId>flyer</groupId>
<artifactId>flyer</artifactId>
<version>1.1.2</version>
</dependency>
- Simple API, from which you can build more elaborate messaging systems.
- Messages are broadcasted to all frames and registered windows, regardless of whether or not they want them (hence, the name)
- Frames can subscribe to specific channels, and can regex-match to broader topics being sent on that channel
- Include flyer.js at the end of your page body
<script type="text/javascript" src="./js/flyer.js"></script>
- In situations where you would use window.open, use flyer.window.open instead. This is required in order to track window references.
- channel
- the channel you wish to broadcast on. default is ””, which stands for *all channels
- topic
- the topic of your broadcast message. default is ””, which stands for *all topics
- data
- any JSON serializable object
- target
- determines what type of target domain is expected to receive this message. By default, the target is “all”, but it can be set to “local”, or a target domain of your choosing.
flyer.broadcast({
channel: "default",
topic: "person.insert",
data: {id: 1, name: "Ben"}
});
flyer.broadcast({
channel: "default",
topic: "person.delete",
data: {id: 1}
});
- channel
- the channel you wish to subscribe to. default is ””, which stands for *all channels
- topic
- the topic you wish to subscribe to. default is ””, which stands for *all topics. Note that this can also be a string representation of a regex expression.
- callback
- callback function of the form function(data, [topic], [channel] [origin]) that you wish to call when the subscription is made.
- origin
- refers to the origin, or domain from which the messages will be received. The default is all, but it can be set to local, or to another origin
flyer.subscribe({
channel: "default",
topic: "person.*",
callback: function(data, topic, channel) {
if (topic == "person.insert") {
console.log("Inserted Person! - " + data.name);
}
else if (topic == "person.delete") {
console.log("Removed Person with id - " + data.id);
}
}
});
follows the same API as window.open
- channel
- the channel you wish to broadcast on. default is ””, which stands for *all channels
- topic
- the topic of your broadcast message. default is ””, which stands for *all topics
- data
- any JSON serializable object
- target
- refers to the target origin, or domain in which to post the message. The default is :all, but it can also be :local, or a target origin of your choosing
(broadcast :channel "default"
:topic "person.insert"
:data {:id 1 :name "Ben"}
:origin :all)
- channel
- the channel you wish to subscribe to. default is ””, which stands for *all channels
- topic
- the topic you wish to subscribe to. default is ””, which stands for *all topics. Note that this can also be a string representation of a regex expression.
- callback
- callback function of the form (fn [data] [topic] [channel] [origin]) that you wish to call when the subscription is made.
- origin
- the origin you wish to subscribe to. This is decides on the domain that messages can be received. The default is :all, but it can also be :local, or an origin of your choice
(subscribe :channel "default"
:origin :local
:topic "person.*"
:callback
(fn [data topic channel]
(condp = topic
"person.insert"
(.log js/console "Inserting person! - " (.-name data))
"person.delete"
(.log js/console "Deleting person! - #" (.-id data)))))
The window URL
The unique name you wish to give the window
key / value pairs of options equivalent to window.open options
(open "frame_login.html" "login-page" :width 400 :height 600)
Examples Outdated
- Clone this Repository
- Install Leiningen
- cd into flyer.js directory
- type lein deps
- resulting flyer.js should now be present in ./resources/public/js/
- In order to communicate with frames and windows that are within an external window, you need to replace window.open with flyer.window.open
- The size of flyer.js is quite big, at a whopping 1mb. This is due to the nature of compilation. Use flyer.min.js to bring this down to 100kb
- Refreshing the parent window of an opened window will break any messages from being broadcasted throughout the application. This is due to the external window frame losing its parent (window.opener).
- external windows can be refreshed without losing communications, however, it requires that flyer.js be included within that html page
flyer.js works by hijacking window.postMessage, and the event generated, which can be attached to through the “message” event
//attaching a listener to frame[0]
window.frame[0].addEventListener("message",
function(event) {
console.log(event.data, event.origin)
});
//posting a message to frame[0]
window.frame[0].postMessage("some message", "*")
It also does a few other things:
- generates a list of frames, by performing a traversal through all of the frames and external windows.
- wraps the functionality into two sane functions.
The full set of steps when performing a broadcast:
- Generate list of frames and external window frames (flyer.traversal)
- Generate a message, by stringifying a defined message object {channel:…, topic:…, data:…} (flyer.messaging)
- For each frame, f, perform f.postMessage(msg, target)
The full steps when performing a subscribe:
- Grab the callback function, and add a “message” event listener
decorated with a set of rules
- Does it have the same channel?
- Does it have the same topic?
- If it isn’t the same topic, does the provided callback topic regex match the broadcasted topic?
- Does it have a lax origin, or is it accepting all origins?
- If it passes the conditions in step 1, the main callback is called with the results of the broadcast. Further conditions can be provided at the developers discretion.