The Hookbox javascript api is contained completely in the hookbox.js file that comes with the Hookbox daemon. The file is served by hookbox at http://HOOKBOX_HOST:HOOKBOX_PORT/static/hookbox.js, but you may serve the file from any location and it will still work.
To connect to hookbox you need to provide the url of the hookbox server, with a "/csp" as the path. For example, if hookbox server is running on host "localhost" and port 8001, (the default) then the to connect:
javascript
var conn = hookbox.connect('http://localhost:8001/csp')
Once the connection has been successfully established, the onopen
callback will be called. You can attach your own callback to catch:
javascript
conn.onOpen = function() { alert("connection established!"); }
If there was an error when connecting the onError
callback will be invoked:
javascript
conn.onError = function(err) { alert("connection failed: " + err.msg); }
To disconnect from hookbox use the conn.disconnect
method:
javascript
conn.disconnect();
NOTE: This method will often not result in a successful disconnect if called in the unload handler for the web page, in which case the user won't be disconnected until they timeout (after about 60 seconds)
As soon as you have a connection object after calling hookbox.connect, you are free to make calls to conn.subscribe, even before the connection is established. These calls will be buffered until after the onOpen event is fired.
To subscribe to a channel use the conn.subscribe function:
javascript
conn.subscribe("my_channel_name");
There is no returned object when calling conn.subscribe; rather, a subscription object is passed to you through the onSubscribed callback once the subscription is successful.
javascript
var subscription = null; conn.onSubscribed = function(channelName, _subscription, args) { subscription = _subscription; }
Its important to understand that the onSubscribed
callback can be called even if you've never made a call to subscribe. This might be because the web application decided to auto_subscribe
you to some channel, or it could be because the user is already logged in and subscribed to multiple channels, though in a different browser window or tab. If the subscribe call is made successfully in another tab, then this tab's Hookbox connection object will also issue an onSubscribed
callback.
Once you have a subsription object, you are able to inspect the channel's attributes, publish to the channel, and receive publishes from other subscribers in the channel.
If the channel is set to have history_size
> 0, then you will have access to history information for that channel:
javascript
>>> subscription.history [["PUBLISH", Object { user="mcarter", payload="greetings!"}], ["SUBSCRIBE", Object { user="mcarter" } ] ... ]
All attributes are read only. The complete list:
historySize
: the length of the history for the channel.history
: a list of the last N elements where N is thehistory_size
attribute of the channelstate
: arbitrary (json) data set on the channel by the web application. This attribute updates automatically when the web application changes it, and an onState callback is issued on the subscription.presenceful
: boolean that signifies rather this channel relays presence informationpresence
: a list of users subscribed to the channel. This is always empty ifpresenceful
is false.reflective
: boolean signifying if this channel reflects publish frames back to the connection that orignated them.
Note in the above example that one of the frames in the history is SUBSCRIBE
. The channel will only relay subscribe and unsubscribe frames to the browser if presenceful
= true is set on the channel by the web application. If it is set, then the subscription object will provide access to a list of users currently subscribed to this channel:
>>> subscription.presence [ "mgh", "mcarter", "desmaj" ]
Whenever a user subscribes or unsubscribes from the channel you will receive an onSubscribe
or onUnsubscribe
callback from the subscription, and the presence attribute will be updated.
javascript
- subscription.onSubscribe = function(frame) {
// the user is now in our presence list assertTrue(subscription.presence.indexOf(frame.user) != -1); alert("user: " + frame.user + " has subscribed!");
}
- subscription.onUnsubscribe = function(frame) {
// the user is no longer in our presence list assertTrue(subscription.presence.indexOf(frame.user) == -1); alert("user: " + frame.user + " has unsubscribed!");
}
Perhaps the most important part of interacting with channels is publishing data receiving published data. You may publish data by calling the subscription.publish
method:
javascript
subscription.publish(42); subscription.publish({foo: "bar"}); subscription.publish(null); subscription.publish([1,2,3, {a: [4,5,6] });
As you can see, any native javascript object that can be transported as JSON
is legal.
Whenever data is published to the channel, the onPublish callback on the subscription will be called. If the reflective
attribute is set on the channel by the web application, then your own calls to publish will cause an onPublish callback as well.
javascript
- subscription.onPublish = function(frame) {
alert(frame.user + " said: " + frame.payload);
}
Remember, frame.payload can be any javascript object that can be represented as JSON
.
It sometimes makes sense for the web application to stash some additional state information on the channel either by setting it in a webhook callback response, or using the rest api. In javascript, the subscription object maintains the state
attribute and issues onState callbacks whenever this attribute is modified. The state cannot be modified by the client; it is unidirectional only. The state
attribute is always a valid json object {}.
javascript
- subscription.onState = function(frame) {
- var updates = frame.updates; // object with the new keys/values and
// modified keys/values
var deletes = frame.deletes; // list containing all deleted keys.
// No need to compute the state from the updates and deletes, its done // for you and stored on subscription.state alert('the name state is: ' + JSON.stringify(subscription.state));
}
You can use the javascript client to request that the user be unsubscribed from a channel with the subscription.cancel
method. When the subscription has been successfully canceled, the conn.onUnsubscribed
will be issued. Keep in mind that the web app may override this request and not allow the user to be unsubscribed and so the onUnsubscribed callback will not be issued.
javascript
subscription = conn.subscribe('foo.bar.baz') ... conn.onUnsubscribed = function(subscription, frame) { alert('successfully unsubscribed from: ' + subscription.channelName); } subscription.cancel();