diff --git a/pusher-js/pusher-js-tests.ts b/pusher-js/pusher-js-tests.ts
index a1c0429b0..c672ff58e 100644
--- a/pusher-js/pusher-js-tests.ts
+++ b/pusher-js/pusher-js-tests.ts
@@ -1,6 +1,7 @@
///
import Pusher = require('pusher-js');
+import { PresenceChannel } from "pusher-js";
var API_KEY: string;
var pusher: Pusher.Pusher;
@@ -86,3 +87,267 @@ channel.unbind(null, handler); // removes `handler` for all events
channel.unbind(null, null, context); // removes all handlers for `context`
channel.unbind(); // removes all handlers on `channel`
+
+//
+//
+// Samples from Pusher Documentation
+//
+//
+
+//
+// JavaScript Quick Start Guide
+//
+
+channel.bind('my-event', function(data: any) {
+ alert('An event was triggered with message: ' + data.message);
+});
+
+//
+// Client API Overview
+//
+
+var options: Pusher.Config;
+
+var channelName: string;
+var privateChannelName: string;
+var presenceChannelName: string;
+var add_member: Function;
+var remove_member: Function;
+var update_member_count: Function;
+var eventName: string;
+var callback: Function;
+var applicationKey: string;
+var log: Function;
+var $: any;
+var data: any;
+
+// Connecting to Pusher
+
+pusher = new Pusher(applicationKey, options);
+
+options = {
+ encrypted: true, // true/false
+ auth: {
+ params: { // {key: value} pairs
+ param1: 'value1',
+ param2: 'value2'
+ },
+ headers: { // {key: value} pairs
+ header1: 'value1',
+ header2: 'value2'
+ }
+ }
+};
+
+pusher = new Pusher('app_key', {
+ auth: {
+ params: {
+ CSRFToken: 'some_csrf_token'
+ }
+ }
+});
+
+pusher = new Pusher('app_key', {
+ auth: {
+ headers: {
+ 'X-CSRF-Token': 'some_csrf_token'
+ }
+ }
+});
+
+pusher = new Pusher('app_key', { cluster: 'eu' });
+
+pusher = new Pusher('app_key', { encrypted: true } );
+
+pusher = new Pusher('app_key');
+pusher.connection.bind( 'error', function( err: any ) {
+ if( err.data.code === 4004 ) {
+ log('>>> detected limit error');
+ }
+});
+
+// Disconnecting from Pusher
+
+pusher.disconnect();
+
+// Connection States
+
+pusher = new Pusher('YOUR_APP_KEY');
+
+pusher.connection.bind('connected', function() {
+ $('div#status').text('Real time is go!');
+});
+
+pusher.connection.bind('connecting_in', function(delay: any) {
+ alert("I haven't been able to establish a connection for this feature. " +
+ "I will try again in " + delay + " seconds.")
+});
+
+pusher.connection.bind('state_change', function(states: any) {
+ // states = {previous: 'oldState', current: 'newState'}
+ $('div#status').text("Pusher's current state is " + states.current);
+});
+
+var connectionState: string = pusher.connection.state;
+
+// Accessing channels
+
+channel = pusher.channel(channelName);
+
+// Public channels
+
+channel = pusher.subscribe(channelName);
+
+pusher.unsubscribe(channelName);
+
+// Private channels
+
+var privateChannel = pusher.subscribe(privateChannelName);
+
+// Presence channels
+
+var presenceChannel: PresenceChannel = pusher.subscribe(presenceChannelName);
+
+var count: number = presenceChannel.members.count;
+
+presenceChannel.members.each(function(member: Pusher.UserInfo) {
+ var userId = member.id;
+ var userInfo = member.info;
+});
+
+var some_user_id: number;
+var user = presenceChannel.members.get(some_user_id);
+
+var me = presenceChannel.members.me;
+
+pusher = new Pusher('app_key');
+presenceChannel = pusher.subscribe('presence-example');
+presenceChannel.bind('pusher:subscription_succeeded', function() {
+ var me = presenceChannel.members.me;
+ var userId = me.id;
+ var userInfo = me.info;
+});
+
+channel = pusher.subscribe('presence-meeting-11');
+
+channel.bind('pusher:subscription_succeeded', function(members: Pusher.Members) {
+ // for example
+ update_member_count(members.count);
+
+ members.each(function(member) {
+ // for example:
+ add_member(member.id, member.info);
+ });
+});
+
+channel.bind('pusher:member_added', function(member: Pusher.UserInfo) {
+ // for example:
+ add_member(member.id, member.info);
+});
+
+channel.bind('pusher:member_removed', function(member: Pusher.UserInfo) {
+ // for example:
+ remove_member(member.id, member.info);
+});
+
+// Pusher Events
+
+channel.bind(eventName, callback);
+
+pusher = new Pusher('APP_KEY');
+channel = pusher.subscribe('APPL');
+channel.bind('new-price',
+ function(data: any) {
+ // add new price into the APPL widget
+ }
+);
+
+var context = { title: 'Pusher' };
+var handler = function(){
+ console.log('My name is ' + this.title);
+};
+channel.bind('new-comment', handler, context);
+
+pusher.bind(eventName, callback);
+
+pusher = new Pusher('APP_KEY');
+var channel1 = pusher.subscribe('test_channel_1');
+var channel2 = pusher.subscribe('test_channel_2');
+var channel3 = pusher.subscribe('test_channel_3');
+
+var eventName = 'new-comment';
+callback = function(data: any) {
+ // add comment into page
+};
+
+// listen for 'new-comment' event on channel 1, 2 and 3
+pusher.bind(eventName, callback);
+
+// Unbinding from Events
+
+channel.unbind(eventName, callback);
+
+pusher = new Pusher('APP_KEY');
+channel = pusher.subscribe('APPL');
+callback = function(data: any) {};
+channel.bind('new-price', callback);
+
+channel.unbind('new-price', callback);
+
+// Pusher channel events
+
+channel.bind('pusher:subscription_succeeded', function() {
+});
+
+pusher = new Pusher('APP_KEY');
+channel = pusher.subscribe('private-channel');
+channel.bind('pusher:subscription_error', function(status: number) {
+ if(status == 408 || status == 503){
+ // retry?
+ }
+});
+
+// Triggering Client Events
+
+var triggered = channel.trigger(eventName, data);
+pusher = new Pusher('YOUR_APP_KEY');
+channel = pusher.subscribe('private-channel');
+channel.bind('pusher:subscription_succeeded', function() {
+ var triggered = channel.trigger('client-someeventname', { your: data });
+});
+
+// Best practice when sending client events
+
+var outputEl = document.getElementById('client_event_example_log');
+var state: any = {
+ currentX: 0,
+ currentY: 0,
+ lastX: undefined,
+ lastY: undefined
+};
+
+pusher = new Pusher("YOUR_APP_KEY");
+channel = pusher.subscribe("private-mousemoves");
+
+// this method should be bound as a 'mousemove' event listener
+document.body.addEventListener('mousemove', onMouseMove, false);
+function onMouseMove(ev: any){
+ ev = ev || window.event;
+ state.currentX = ev.pageX || ev.clientX;
+ state.currentY = ev.pageY || ev.clientY;
+}
+
+setInterval(function(){
+ if(state.currentX !== state.lastX || state.currentY !== state.lastY){
+ state.lastX = state.currentX;
+ state.lastY = state.currentY;
+
+ var text = document.createTextNode(
+ 'Triggering event due to state change: x: ' + state.currentX + ', y: ' + state.currentY
+ );
+ outputEl.replaceChild( text, outputEl.firstChild );
+
+ channel.trigger("client-mouse-moved", {x:state.currentX, y: state.currentY});
+ }
+}, 300); // send every 300 milliseconds if position has changed
+
diff --git a/pusher-js/pusher-js.d.ts b/pusher-js/pusher-js.d.ts
index 393cba720..9306faa8f 100644
--- a/pusher-js/pusher-js.d.ts
+++ b/pusher-js/pusher-js.d.ts
@@ -18,6 +18,14 @@ declare module "pusher-js" {
allChannels(): Channel[];
bind(eventName: string, callback: Function): Pusher;
bind_all(callback: Function): Pusher;
+ disconnect(): void;
+ key: string;
+ config: Config; //TODO: add GlobalConfig typings
+ channels: any; //TODO: Type this
+ global_emitter: EventsDispatcher;
+ sessionId: number;
+ timeline: any; //TODO: Type this
+ connection: ConnectionManager;
}
interface Config {
@@ -103,15 +111,117 @@ declare module "pusher-js" {
headers?: { [key: string]: any };
}
- interface Channel {
- bind(eventName: string, callback: Function, context?: any): Channel;
- bind_all(callback: Function): Channel;
- unbind(eventName?: string, callback?: Function, context?: any): Channel;
- unbind_all(eventName?: string, callback?: Function): Channel;
- trigger(eventName: string, data?: any): any;
+ interface GenericEventsDispatcher extends EventsDispatcher {
+ bind(eventName: string, callback: Function, context?: any): Self;
+ bind_all(callback: Function): Self;
+ unbind(eventName?: string, callback?: Function, context?: any): Self;
+ unbind_all(eventName?: string, callback?: Function): Self;
+ emit(eventName: string, data?: any): Self;
+ }
+
+ interface Channel extends GenericEventsDispatcher {
+ /** Triggers an event */
+ trigger(eventName: string, data?: any): boolean;
pusher: Pusher;
name: string;
subscribed: boolean;
+ /**
+ * Authenticates the connection as a member of the channel.
+ * @param {String} socketId
+ * @param {Function} callback
+ */
+ authorize(socketId: string, callback: (data: any) => void): void;
+ }
+
+ interface EventsDispatcher {
+ bind(eventName: string, callback: Function, context?: any): EventsDispatcher;
+ bind_all(callback: Function): EventsDispatcher;
+ unbind(eventName?: string, callback?: Function, context?: any): EventsDispatcher;
+ unbind_all(eventName?: string, callback?: Function): EventsDispatcher;
+ emit(eventName: string, data?: any): EventsDispatcher;
+ }
+
+ interface ConnectionManager extends GenericEventsDispatcher {
+ key: string;
+ options: any; //TODO: Timeline.js
+ state: string;
+ connection: any; //TODO: Type this
+ encrypted: boolean;
+ timeline: any; //TODO: Type this
+ connectionCallbacks: {
+ message: (message: string) => void;
+ ping: () => void;
+ activity: () => void;
+ error: (error: any) => void;
+ closed: () => void;
+ };
+ errorCallbacks: {
+ ssl_only: () => void;
+ refused: () => void;
+ backoff: () => void;
+ retry: () => void;
+ };
+ handshakeCallbacks: {
+ ssl_only: () => void;
+ refused: () => void;
+ backoff: () => void;
+ retry: () => void;
+ connected: (handshake: any) => void; //TODO: Type this
+ };
+ /**
+ * Establishes a connection to Pusher.
+ *
+ * Does nothing when connection is already established. See top-level doc
+ * to find events emitted on connection attempts.
+ */
+ connect(): void;
+ /**
+ * Sends raw data.
+ * @param {String} data
+ */
+ send(data: string): boolean;
+ /** Sends an event.
+ *
+ * @param {String} name
+ * @param {String} data
+ * @param {String} [channel]
+ * @returns {Boolean} whether message was sent or not
+ */
+ send_event(name: string, data: string, channel: string): boolean;
+ /** Closes the connection. */
+ disconnect(): void;
+ isEncrypted(): boolean;
+ }
+
+ interface PresenceChannel extends Channel {
+ members: Members;
+ }
+
+ interface Members {
+ /**
+ * Returns member's info for given id.
+ *
+ * Resulting object containts two fields - id and info.
+ *
+ * @param {Number} id
+ * @return {Object} member's info or null
+ */
+ get(id: number): T;
+ /**
+ * Calls back for each member in unspecified order.
+ *
+ * @param {Function} callback
+ */
+ each(callback: (member: any) => void): void;
+ members: { [id: number]: UserInfo };
+ count: number;
+ myID: number;
+ me: UserInfo;
+ }
+
+ interface UserInfo {
+ id: number;
+ info: T;
}
}
@@ -119,4 +229,3 @@ declare module "pusher-js" {
export = pusher;
}
-