Client - JavaScript - Guide

Before reading this document, please first take a look at Realtime Engine Guide.

Browser Compatibility

The basic functions are compatible with IE8+ and various modern browsers of latest version, including Chrome, FireFox, Safari, and so forth.

The recording and sending of audio and video messages in Chat mode only supports Chrome and Firefox.

API Documentation

This guide only provides a brief integration description. For more details on the usage, see API Documentation.

Installation

bower

Download from Here, or install using bower:

bower install tuisongbao-realtime-engine-client

Then reference to engine.js or engine.min.js under the installation directory:

<script src="/path/to/engine.min.js"></script>

Preliminaries

  • Run Engine.debug.enable('engine:*') in Console, the browser development tool to turn on the debug log, and run Engine.debug.disable() to turn it off.

Configure and Establish Connection

Pass various options through the second parameter while instantiating Engine:

var options = {
    // Authenticate user address
    authEndpoint: 'http://yourdomain.com/tuisongbao_engine/auth',
    // Authenticate user request method, `xhr` by default, which uses XMLHttpRequest, but this method has cross-domain problem on IE8/9. If the authEndpoint you configured is cross domain and needs to support IE8/9, you should use `jsonp` and meanwhile please ensure your server supports the `jsonp` requests. This setting will take effect on all browsers, not only on IE 8/9
    authTransport: 'jsonp',
    // Optional, if configured, the authentication request will carry this value to demonstrate user identity. When used together with jsonp, if the value is Object, it will be serialized into JSON string
    authData: 'authData-sample'
    // When using extensions (Chat local cache and multimedia message), you must specify the parent path on the Web server for "engine.js"
    basePath: '/engine/clientJavaScript/',
    // Optional, the role is that SDK can support the invocation of certain APIs when the network is not available. For more details, see Cache Policy in chapter Chat.
    supportOffline: true,
    // Chat related options, no need to configure them if the Chat mode is not used
    chat:
        // Enable local cache, which supports Chrome, Firefox and IE11
        enableCache: true,
        // Enable the delivery function of multimedia messages (images, audios and videos). Enabling this option will also load additional resouce files asynchronously
        enableMediaMessage: true
};

var engine = new Engine('YOUR_APP_ID', options);

After instantiation, connection will be automaticalled established, and you can use the Engine instance that is returned for later various operations.

Connection Event

You can listen for the following Events on the engine.connection object:

  • state_changed: Triggered when connect state is changed.
  • connecting_in: Notify how soon the next reconnection will be made.
  • initialized, connected, disconnected, connecting and failed are triggered respectively when Connection enters the corresponding states.
  • error: Triggered when an error occurs.
connection.bind('state_changed', function (states) {
    console.log(states.previous, states.current);
});

connection.bind('connecting_in', function (delay) {
    console.log('Reconnection will be made' + delay + 'ms later');
});

connection.bind('connecting', function () {
    // Prompt the user that the network is unstable and it is trying to make a connection
});

connection.bind('error', function (err) {
    console.log(err);
});

Get SocketId

connection.bind('connected', function () {
    console.log(connection.socketId);
});

Disconnect

Call disconnect on the connection object:

connection.disconnect();

To restore a connection, call connect:

connection.connect();

Pub/Sub

The Pub/Sub related functions are mainly completed through engine.channels.

Get channels, the management object of channel

var channels = engine.channels;

Subscribe Channel

var coolChannel = channels.subscribe('cool-channel');

This method will return the Channel instance, which can be used for such operations as bind, and so on.

Additionally, you can get the Channel instance that has been subscribed through the find method of channels:

var coolChannel = channels.find('cool-channel');

Unsubscribe though the unsubscribe method:

channels.unsubscribe('cool-channel');

Bind Event Handler

coolChannel.bind('cool-event', function (data) {
    // processing logic
});

This operation is only applied to the current Channel, that is to say you can use the same Event name on other Channels.

Unbind through the unbind method:

// Only unbind a certain handler of this Event
coolChannel.unbind('cool-channel', handler);
// Unbind all the handlers of this Event
coolChannel.unbind('cool-channel');

Channel Event

All the Channels can handle the subscription result by listening for the engine:subscription_succeeded and engine:subscription_error Event:

privateChannel.bind('engine:subscription_succeeded', function () {
    console.log('subscription channel ' + privateChannel.name + ' successful');
});

privateChannel.bind('engine:subscription_error', function (err) {
    console.log('subscription channel ' + privateChannel.name + ' failed', err);
    // Re-subscribe ?
});

As for Presence Channel and engine:subscription_succeeded, the handler will get an extra parameter users, and this object has the following attributes:

{
    // The number of users who are online currently on this Channel
    count: 100,
    // Receive a method as a parameter to be used to traverse current online users
    each: [Function],
    // Current users
    me: {
        id: '1111',
        info: 'Fake user info for socket 111111 on channel presence-demo'
    }
}

An example is shown below:

presenceChannel.bind('engine:subscription_succeeded', function (users) {
    console.log('subscription channel ' + presenceChannel.name + ' successful');
    console.log('number of users:' + users.count);

    console.log('Traversing users starts:');
    users.each(function (user) {
        console.log(user.id, user.info);
    });
    console.log('Traversing users ends');

    console.log('Current users:', users.me.id, users.me.info);
});

Note that the users object can also be obtained directly on the Presence Channel object:

console.log(presenceChannel.users);

In addition, you can listen for engine:user_added and engine:user_removed on the Presence Channel object to handle notifications of users’ coming online or going offline:

presenceChannel.bind('engine:user_added', function (user) {
    console.log('new user:', user.id, user.info);
});

presenceChannel.bind('engine:user_removed', function (user) {
    console.log('The user went offline:', user.id, user.info);
});

Chat

The Chat related functions are mainly completed through engine.chatManager.

ChatManager Event

chatManager.bind('login:succeeded', function() {
    console.log('Successfully signed in');
});

chatManager.bind('login:failed', function(err) {
    console.log('Failed to sign in');
});

chatManager.bind('message:new', function(message) {
    console.log('New message');
});

For more Events, see API Documentation.

Sign In

chatManager.login({
    authData: chatUserId
});

var onLoginSucceeded = function() {
    console.log('login succeeded');
};
var onLoginError = function(err) {
    console.log('login failed:', err);
};

engine.chatManager.bind('login:succeeded:', onLoginSucceeded);
engine.chatManager.bind('login:failed:', onLoginError);

Sign Out

chatManager.logout().then(function() {
    console.log('Successfully signed out');
}).catch(function(err){
    console.log('Failed to sign out' + err);
});

Get Current Users and Their Sign-in State

// The content is the userData that is returned by your server when authenticating users
console.log(engine.chatManager.user);

// Enumeration values: initialized, loggingIn, loggedIn, failed, loggedOut
console.log(engine.chatManager.state);

Get Conversation List

Get the conversation list through chatManager.conversations.

Promise use:

conversations.load().then(function(conversations) {
    console.log('Successfully got the list of the Conversation instance');
}).catch(function(err) {
    console.log('Failed to get. Please try later');
});

Callback use

conversations.load({
    onSuccess: function(conversations) {
        console.log('Successfully got the list of the Conversation instance');
    },
    onError: function(err) {
        console.log('Failed to get. Please try later');
    }
});

For the description of Promise and Callback, see Here.

Get ChatConversation Instance

Developers can call the methods on the ChatConversation instance to send messages, delete conversations, reset unread messages, and so forth. It can be obtained from the coversation list as mentioned in the above example, or you can acquire a specific conversation through conversations.loadOne:

conversations.loadOne({
    type: 'singleChat',
    target: '1111'
}).then(function(_conversation) {
    conversation = _conversation
});

Get Conversation History

conversation.loadMessages({
    // Conversation type, singleChat(single chats)or groupChat(group chats)
    type: 'singleChat',
    // With who (the ID of chat counterpart), userId or groupId
    target: '1111',
    // Optional
    startMessageId: 100,
    // Optional
    endMessageId: 300,
    // Optional, 20 by defaut, a max of 100 is allowed
    limit: 20
    // Please refer to the API documentation for other parameters
}).then(function(messages) {
    console.log('Successfully got conversation messages');
    // When the support of offline function is enabled, the messages stored offline have three states, including `sending`, `succeeded` and `failed`. When the state is `sending`, messages will be resent before calling loadMessages, during which the message state may be changed. If you want to trace the message state, you can listen for the `state:changed` event
    messages.map(function (message){
        if(message.state !== 'succeeded'){
            message.bind('state:changed', function (state){
                // Message state is changed, and the logic of refreshing UI can be coded here
                console.log("State before change:", state.previous);
                console.log("Curtrent state", state.current);
            });
        }
    });
}).catch(function(err) {
    console.log('Failed to get. Please try later');
});

Reset Unread Messages of a Cnversation as 0

conversation.resetUnread();

Delete Conversations

conversation.delete().then(function() {
    console.log('Successfully deleted the conversation');
}).catch(function(err) {
    console.log('Failed to delete. Please try later');
});

Listen for New Messages

Listen for new messages by listening for message:new Event on the ChatConversation object:

conversation.bind('message:new', function(newMessage) {
    console.log('You received from' + newMessage.from + 'a new message');

    // type enumerations: 'text', 'image', 'voice', 'video', 'location', 'event'
    console.log('The message type is:' + newMessage.content.type);

    if (newMessage.content.file) {
        console.log('Address of multimedia file download:' + newMessage.content.file.url);
        console.log('Size of multimedia file:' + newMessage.content.file.size);
    } else if (newMessage.content.location) {
        console.log('The location (point of interest) is:' + newMessage.content.location.poi);
    } else if (newMessage.content.event) {
        console.log(' Event type:' + newMessage.content.event.type);
    } else {
        console.log('What you sent is text message, and content is:' + newMessage.content.text);
    }
    console.log('Additional information:' + newMessage.content.extra);
    console.log('Delivery Time:' + newMessage.createdAt);
});

Send Text Messages

conversation.sendMessage({
    type: 'text',
    text: 'Hello World!',
    // Optional, addition information, used to implement custom business logic of the application
    extra: {}
}).then(function(message) {
    console.log(message);
}).catch(function(err) {
    console.log('Failed to send. Please try later');
});

Send Image Messages

Get ImageUploader

conversation.getImageUploader({
    // Trigger the ID of the DOM element selected by a file
    browseButton: 'imageMessage',
    // Optional, dragging the ID of the DOM element of an area can implement drag and upload
    dropElementId: 'messageContainer',
    // Optional, additional information, used to implement custom business logic of the application
    extra: {}
}).then(function(imageUploader) {
    console.log('Successfully got imageUploader,and you can listen for Event on it');
}).catch(function(err) {
    console.log('Failed to get. Please try later');
});

After initialization, clicking browseButton will pop up the file selection dialog, and after selecting a file, the file will be automatically uploaded and the message will be sent.

imageUploader.bind('failed', function(err) {
    console.log('imageUploader initialization failed:' + err);
});
imageUploader.bind('message:sent', function(sentMessage) {
    console.log('Image message sent successfully:' + sentMessage);
});
imageUploader.bind('message:sendFailed', function(err) {
    console.log('Image message sending failed:' + err);
});
imageUploader.bind('state:changed', function(state) {
    // The value of the state may be: initialized(Initialization complete),uploaded(Uploaded successfully ),uploading(Is uploading),failed(Initialization failed)
    console.log('The state of uploading image messages:' + state);
});

Destroy Ojbects

// Unbind all the handlers of this Event and destroy the imageUploader object as well as the DOM nodes selected by the corresponding files
imageUploader.destroy()

Send Audio Messages

Audio message sending is completed through VoiceUploader.

VoiceUploader provides a set of methods of sending audio messages. For more details, see API](docs/engineAPI/clientJavaScript/index.html#ChatVoiceUploader).

  • startRecord: Begin to record an audio
  • stopRecord: Stop recording a audio
  • send: Send an audio recorded

Get VoiceUploader

conversation.getVoiceUploader({
    // Optional, additional information, used to implement custom business logic of the application
    extra: {}
}).then(function(voiceUploader) {
    console.log('Successfully got voiceUploader,and you can listen for Event on it');
}).catch(function(err) {
    console.log('Failed to get. Please try later');
});
voiceUploader.bind('failed', function(err) {
    console.log('VoiceUploader initialization failed:' + err);
});
voiceUploader.bind('message:sent', function(sentMessage) {
    console.log('Audio message sent successfully:' + sentMessage);
});
voiceUploader.bind('message:sendFailed', function(err) {
    console.log('Audio message sending failed:' + err);
});
voiceUploader.bind('state:changed', function(state) {
    // The value of the state may be: initialized(Initialization complete),recording(Is recording),recorded(Recorded successfully),uploaded(Uploaded successfully),uploading(Is uploading),failed(Initialization failed)
    console.log('The state of rcording and uploading audio messages:' + state);
});
voiceUploader.bind('record:started', function() {
    console.log('Recording started');
});
voiceUploader.bind('record:stopped', function(blob, duration) {
    console.log('Recording ended, and return the blob object as well as length');
});

Destroy Objects

// Unblind all the handlers of this Event, and destroy the voiceUploader object
voiceUploader.destroy()

Send Video Messages

Video message sending is completed through VideoUploader.

VideoUploader provides a set of methods of sending video messages. For more details, see API.

  • startRecord: Start to record a video
  • stopRecord: Stop recording a video
  • send: Send a video recorded

Get VideoUploader

conversation.getVideoUploader().then(function(videoUploader) {
    console.log('Successfully got videoUploader, and you can listen for the Event on it');
}).catch(function(err) {
    console.log('Failed to get. Please try later');
});
videoUploader.bind('failed', function(err) {
    console.log('VideoUploader initialization failed:' + err);
});
videoUploader.bind('message:sent', function(sentMessage) {
    console.log('Video message sent successfully:' + sentMessage);
});
videoUploader.bind('message:sendFailed', function(err) {
    console.log('Video message sending failed:' + err);
});
videoUploader.bind('state:changed', function(state) {
    // The value of the state may be: initialized(Initialization complete),recording(Is recording),recorded(Recorded successfully),uploaded(Uploaded successfully),uploading(Is uploading),failed(Initialization failed)
    console.log('The state of recording and uploading video messages:' + state);
});
voiceUploader.bind('record:started', function() {
    console.log('Recording started');
});
videoUploader.bind('record:stopped', function(blob, duration) {
    console.log('Recording ended, and return the blob object as well as length');
})
// Unbind all the Events, and destroy the videoUploader object as well as the DOM nodes of the corresponding video recording
videoUploader.destroy()

Send Location Data Messages

chatManager.locationHelper.getLocation().then(function(location) {
    // Return the longitude and latitude of the current location
    console.log('The current location is:' + location);
    // Send location data messages
    conversation.sendMessage({
        type: 'location',
        location: {
            // Latitude
            lat: location.lat
            // Longitude
            lng: location.lng
            // Optional, point of interest, if not provided, TuiSongBao will attempt to get it from Baidu Maps
            poi: location.poi
        },
        // Optional, additional information, used to implement the custom business logic of the application
        extra: {}
    }).then(function(message) {
        console.log(message);
    }).catch(function() {
        console.log('Failed to send. Please try later');
    });
}).catch(function(err) {
    console.log('err: ' + err);
});

Get Group List

You can get the group list through chatManager.groups:

// Have no parameters, and this interface is used to sync up the latest group list
chatManager.groups.load({
    // Optional, filter according to ID
    groupId: '54c4951f50c5e752c0a512a1'
}).then(function(groups) {
    console.log(groups);
}).catch(function(err) {
    console.log('Failed to get. Please try later');
});

Create Groups

chatManager.groups.create({
    // Whether a group is public (true: The request for joining a group from any user will be directly passed without verification; false: Need the administrator to verify)
    isPublic: true,
    // Except the creator (owner), whether other group users can send invitations to join the group (true: allowed; false: not allowed)
    userCanInvite: true
    // Original members, if successfully created, group invitations will be sent to these users, if acceptAllJoinGroupInvitation of an invitee is true, he or she can directly join the group
    inviteUserIds: ['1111', '2222']
}).then(function(_group) {
    group = _group;
}).catch(function(err) {
    console.log('Failed to create. Please try later');
});

Get Group User List

group.loadUsers().then(function(users) {
    console.log('Successfully got group users');
}).catch(function(err) {
    console.log('Failed to get. Please try later');
});

Structure of users:

[{
    userId: '1111',
    // Online state, online or offline
    presence: 'online'
}]

Invite Users to Joint a Group

group.inviteUsers({
    userIds: ['1111']
}).then(function() {
    console.log('Successfully got the group users');
}).catch(function(err) {
    console.log('Failed to get. Please try later');
});

Remove Users from a Group

group.removeUsers({
    userIds: ['1111']
}).then(function(users) {
    console.log('Successfully removed users');
}).catch(function(err) {
    console.log('Failed to remove. Please try later');
});

Leave a Group Proactively

group.leave().then(function() {
    console.log('Successfuly left the group');
}).catch(function(err) {
    console.log('Failed to leave. Please try later');
});

Supplement

About Promise

All the methods support the two asynchronous invocations of promise and callback in ChatManager except login. For more details, see [API Documentation] (docs/engineAPI/clientJavaScript/).

About Event

ChatManager, ChatConversation, ChatUploader, and so on are all inherited from EventEmitter, so the bind method can be used on all these objects to bind event handlers as well as the unbind method to unbind event handlers.

About “extra”, the Additional Information of Messages

All message types support “extra” to implement the custom business logic of the application.

About Permissions

Sending audio, video and location data messages needs to request the browser for the corresponding permissions. SDK will send the request to the browser in due time, and only after users consent can the messages be sent.

Notes

  • Except sign-in, all the APIs must be called after users sign in successfully, otherwise an error will be returned.

Upgrade Steps

If no special notes, just replacing the SDK would be enough.

v1.0.0 to 2.0.0

  • Replace the SDK
  • pub/sub related methods are moved to engine.channels
  • On ChatManager, all the APIs are delivered to each sub module based on the function except login and logout. For more details, see [API Documentation] docs/engineAPI/clientJavaScript/).

v0.9.2 to 1.0.0

  • Replace the SDK
  • chatManager:
    • Removed chatManager.loggedIn , and added chatManager.state
  Back To Top