In standard modern web applications, client-side scripts are either standalone, or tightly coupled with one another. Browser extensions and Greasemonkey userscripts, on the other hand, are running in a sandbox beneath an artificial window
object and can only be loosely coupled via message-passing by sending custom DOM events, or by using proprietary APIs.
The problem is that tight coupling is often undesirable, proprietary APIs are non-portable and custom events are a very crude means of communication prone to misconfiguration and event name collisions. jBus, on the other hand, is a cross-extension messaging architecture designed with the prevention of naming collisions in mind, which features a simple but expressive API and which enables loose coupling between any two pieces of JavaScript code sharing as little as a DOM event target.
jBus is compatible with any browser, which supports ECMAScript 3+ including the extensions described in the WHATWG JavaScript specification, the window.document
object as described in the WHATWG HTML specification, DOM 2 Events as described in the DOM 2 Events W3C recommendation and the CustomEvent
interface as described in the DOM 3 Events W3C working draft. The list includes:
- Opera 11+
- Mozilla/Firefox 6+
- Internet Explorer 9+
- Webkit 533.3+
- Safari 5.1+
- Chrome
The assembly of the jBus source files requires a POSIX.2-compliant environment. To begin the assembly, run the make build
command in the uppermost folder of the project. At the end of the process, the following files will be present in the build
folder:
jBus.js
-- A static build of jBus, which defines:- The
JBus.Node
object constructor. - The
JBus.Scope
object constructor and method.
- The
jBus.debug.js
-- A static build of jBus, which defines:- Logs any outgoing messages to the console.
- Defines:
- The
JBus.Node
object constructor. - The
JBus.Scope
object constructor and method. - The
JBus.Node.messages.*
object constructors. - The
JBus.Node.services.*
methods.
- The
The minification of the jBus source files requires the closure-compiler
binary of the Closure Compiler by Google to be executable and to reside within one of the directories in the PATH
environment variable. To begin the minification, run the make min
command in the uppermost folder of the project. At the end of the process, the following files will be present in the build
folder:
jBus.min.js
-- A static and minified build of jBus, which defines:- The
JBus.Node
object constructor. - The
JBus.Scope
object constructor and method.
- The
jBus.min.debug.js
-- A static and minified build of jBus, which:- Logs any outgoing messages to the console.
- Defines:
- The
JBus.Node
object constructor. - The
JBus.Scope
object constructor and method. - The
JBus.Node.messages.*
object constructors. - The
JBus.Node.services.*
methods.
- The
The latest minified jBus builds are also available online:
Alternatively, you can use any other minification tool or service, as long as the license notice is kept intact.
If you wish to dynamically load the latest version of jBus into your userscript, use the @require
metadata key as follows:
// ==UserScript==
// ...
// @require http://tiny.cc/jBus
// ...
// ==/UserScript==
If you wish to statically embed jBus into your userscript, include the contents of the jBus build you wish to use directly into your userscript. Make sure you include it before any calls to the library.
If you prefer to dynamically load the latest version of jBus into your userscript, but you want to include a static fallback, then the best practice is the following:
- Use the
@require
metadata key to attempt to load the latest version of jBus into your userscript. - Include the contents of the jBus build you wish to use directly into your userscript with the following modification:
* Replace the initial
var JBus =
withvar JBus; if(!JBus) JBus =
.
This will allow users, whose script managers don't support the @require
metadata key, to fall back on the statically embedded jBus library.
To be able to use jBus on your web page, input the following code in either the head or the body of the webpage. Make sure you include it before any scripts that use the library:
<script src="jBus.js"></script>
Replace jBus.js
with a pathname to the jBus build you wish to use.
By loading the src/test.html
file in your browser, you can run a suite of tests against the src/jBus.js
and src/framework.js
files. You can use this to check, whether:
- jBus is compatible with a given browser.
- Your modified version of jBus works as intended.
If the you only want to check browser compatibility, the online version of the test suite may be a more convenient route for you.
- Isn't this essentially what custom events are for?
It is. jBus is an [architecture](docs/architecture.md) built on top of custom events, which also allows for [scoping](docs/examples.md#scoping), [dependencies](docs/examples.md#dependencies) and [unicast + multicast messaging](docs/architecture.md#addresses). If global broadcasting of events is all you need, you can equally well use [custom events][CustomEvent] directly.
- Isn't this essentially what storage events are for?
Not quite. While it is true that you can store data in the [`localStorage`][localStorage] and [`sessionStorage`][sessionStorage] objects and any listener will be notified about your changes, you can only store textual data, whereas a [custom events][CustomEvent]-based architecture (such as jBus) allows you to pass around any kind of data including functions along with their [scope chain][Multiply-nested functions], which doesn't survive serialization to string.
By the same token, [storage events][] *do* offer functionality, which cannot be achieved using [custom events][CustomEvent]. Since the [`localStorage`][localStorage] object is specific to a protocol and a domain (hereinafter an origin), any change to the object will emit a [storage event][storage events] in any open window / iframe containing the [`localStorage`][localStorage] object of the given origin other than the event dispatcher.
This allows for functionality such as pausing music playback in all windows other than the current one (as implemented by [soundcloud.com](http://soundcloud.com)). By contrast, a [custom events][CustomEvent]-based architecture (such as jBus) only allows for event dispatchment within the original window and other windows and iframes, to which there is a reference.
It should now be clear that [custom events][CustomEvent]-based architectures (such as jBus) and [storage events][]-based architectures (such as [ding][]) each offer capabilities, which are mutually complementary, rather than one being a subset of the other.
Copyright (c) 2014 Vít Novotný
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.