datachannel
v1.0.0
Published
DataChannel.js is a JavaScript library useful to write many-to-many i.e. group file/data sharing or text chat applications. Its syntax is easier to use and understand. It highly simplifies complex tasks like any or all user rejection/ejection; direct mess
Downloads
18
Maintainers
Readme
DataChannel.js : A JavaScript wrapper library for RTCDataChannel APIs / Demos
npm install datachannel
# or
bower install datachannel
DataChannel.js is a JavaScript library useful to write many-to-many i.e. group file/data sharing or text chat applications. Its syntax is easier to use and understand. It highly simplifies complex tasks like any or all user rejection/ejection; direct messages delivery; and more.
If you want all DataChannel.js functionalities along with media streaming and runtime additions/deletions then RTCMultiConnection.js is a good chose with similar APIs/syntax.
Features
- Direct messages � to any user using his
user-id
- Eject/Reject any user � using his
user-id
- Leave any room (i.e. data session) or close entire session using
leave
method - File size is limitless!
- Text message length is limitless!
- Size of data is also limitless!
- Fallback to firebase/socket.io/websockets/etc.
- Users' presence detection using
onleave
- Latency detection
- Multi-longest strings/files concurrent
- File queue support added. Previously shared files will be auto transmitted to each new peer.
Demos using DataChannel.js
- DataChannel basic demo
- Auto Session Establishment and Users presence detection
- Text Chat using Pusher and DataChannel.js
Try a Quick Demo (Text Chat)
<script src="//cdn.webrtc-experiment.com/DataChannel.js"> </script>
<button id="setup-datachannel" style="width:30%;">Open NEW DataChannel</button>
<input type="text" id="chat-input" disabled style="font-size: 2em; width: 65%;"><br />
<div id="chat-output"></div>
<script>
var chatOutput = document.getElementById('chat-output');
var chatInput = document.getElementById('chat-input');
chatInput.onkeypress = function (e) {
if (e.keyCode != 13) return;
channel.send(this.value);
chatOutput.innerHTML = 'Me: ' + this.value + '<hr />' + chatOutput.innerHTML;
this.value = '';
};
var channel = new DataChannel();
channel.onopen = function (userid) {
chatInput.disabled = false;
chatInput.value = 'Hi, ' + userid;
chatInput.focus();
};
channel.onmessage = function (message, userid) {
chatOutput.innerHTML = userid + ': ' + message + '<hr />' + chatOutput.innerHTML;
};
channel.onleave = function (userid) {
chatOutput.innerHTML = userid + ' Left.<hr />' + chatOutput.innerHTML;
};
// search for existing data channels
channel.connect();
document.querySelector('button#setup-datachannel').onclick = function () {
// setup new data channel
channel.open();
};
</script>
First Step: Link the library
<script src="//cdn.webrtc-experiment.com/DataChannel.js"></script>
Last Step: Start using it!
var channel = new DataChannel('[optional] channel-name');
channel.send(file || data || 'text-message');
open/connect data channels
// to create/open a new channel
channel.open('channel-name');
// if someone already created a channel; to join it: use "connect" method
channel.connect('channel-name');
onopen
and onmessage
If you're familiar with WebSockets; these two methods works in the exact same way:
channel.onopen = function(userid) { }
channel.onmessage = function(message, userid, latency) { }
user-ids
can be used to send direct messages or to eject/leave any user:
ondatachannel
Allows you show list of all available data channels to the user; and let him choose which one to join:
channel.ondatachannel = function(data_channel) {
channel.join(data_channel);
// or
channel.join({
id: data_channel.id,
owner: data_channel.owner
});
// id: unique identifier for the session
// owner: unique identifier for the session initiator
};
Use custom user-ids
channel.userid = 'predefined-userid';
Remember; custom defined user-id
must be unique username.
Direct messages
channel.channels[userid].send(file || data || 'text message');
Eject/Reject users using their user-ids
channel.eject(userid); // throw a user out of your room!
Close/Leave the entire room
channel.leave(); // close your own entire data session
Detect users' presence
channel.onleave = function(userid) { };
Auto Close Entire Session
When room initiator leaves; you can enforce auto-closing of the entire session. By default: it is false
:
channel.autoCloseEntireSession = true;
It means that session will be kept active all the time; even if initiator leaves the session.
You can set autoCloseEntireSession
before calling leave
method; which will enforce closing of the entire session:
channel.autoCloseEntireSession = true;
channel.leave(); // closing entire session
uuid
for files
You can get uuid
for each file (being sent) like this:
channel.send(file);
var uuid = file.uuid; // "file"-Dot-uuid
To Share files
var progressHelper = {};
// to make sure file-saver dialog is not invoked.
channel.autoSaveToDisk = false;
channel.onFileProgress = function (chunk, uuid) {
var helper = progressHelper[chunk.uuid];
helper.progress.value = chunk.currentPosition || chunk.maxChunks || helper.progress.max;
updateLabel(helper.progress, helper.label);
};
channel.onFileStart = function (file) {
var div = document.createElement('div');
div.title = file.name;
div.innerHTML = '<label>0%</label> <progress></progress>';
appendDIV(div, fileProgress);
progressHelper[file.uuid] = {
div: div,
progress: div.querySelector('progress'),
label: div.querySelector('label')
};
progressHelper[file.uuid].progress.max = file.maxChunks;
};
channel.onFileSent = function (file) {
progressHelper[file.uuid].div.innerHTML = '<a href="' + file.url + '" target="_blank" download="' + file.name + '">' + file.name + '</a>';
};
channel.onFileReceived = function (fileName, file) {
progressHelper[file.uuid].div.innerHTML = '<a href="' + file.url + '" target="_blank" download="' + file.name + '">' + file.name + '</a>';
};
function updateLabel(progress, label) {
if (progress.position == -1) return;
var position = +progress.position.toFixed(2).split('.')[1] || 100;
label.innerHTML = position + '%';
}
File Queue
File Queue support added to make sure newly connected users gets all previously shared files.
You can see list of previously shared files:
console.log( channel.fileQueue );
Auto-Save file to Disk
By default; autoSaveToDisk
is set to true
. When it is true
; it will save file to disk as soon as it is received. To prevent auto-saving feature; just set it false
:
channel.autoSaveToDisk = false; // prevent auto-saving!
channel.onFileReceived = function (fileName, file) {
// file.url
// file.uuid
hyperlink.href = file.url;
};
Latency Detection
channel.onmessage = function(message, userid, latency) {
console.log('latency:', latency, 'milliseconds');
};
Concurrent Transmission
You can send multiple files concurrently; or multiple longer text messages:
// individually
channel.send(fileNumber1);
channel.send(fileNumber2);
channel.send(fileNumber3);
// or as an array
channel.send([fileNumber1, fileNumber2, fileNumber3]);
channel.send('longer string-1');
channel.send('longer string-2');
channel.send('longer string-3');
Errors Handling
// error to open data ports
channel.onerror = function(event) {}
// data ports suddenly dropped
channel.onclose = function(event) {}
Data session direction
Default direction is many-to-many
.
channel.direction = 'one-to-one';
channel.direction = 'one-to-many';
channel.direction = 'many-to-many';
=
For signaling; please check following page:
https://github.com/muaz-khan/WebRTC-Experiment/blob/master/Signaling.md
Remember, you can use any signaling implementation that exists out there without modifying any single line! Just skip below code and open above link!
Resources
- Video Presentation for
openSignalingChannel
: https://vimeo.com/91780227 - Documentation for
openSignalingChannel
: http://www.rtcmulticonnection.org/docs/openSignalingChannel/
Use your own socket.io for signaling
dataChannel.openSignalingChannel = function(config) {
var channel = config.channel || this.channel || 'default-channel';
var socket = io.connect('/?channel=' + channel);
socket.channel = channel;
socket.on('connect', function () {
if (config.callback) config.callback(socket);
});
socket.send = function (message) {
socket.emit('message', {
sender: dataChannel.userid,
data : message
});
};
socket.on('message', config.onmessage);
};
Use Pusher for signaling
A demo & tutorial available here: http://pusher.com/tutorials/webrtc_chat
Another link: http://www.rtcmulticonnection.org/docs/openSignalingChannel/#pusher-signaling
Use firebase for signaling
// firebase stores data on their servers
// that's why transmitting room once
// unlike other signalling gateways; that
// doesn't stores data on servers.
channel.transmitRoomOnce = true;
channel.openSignalingChannel = function (config) {
channel = config.channel || this.channel || 'default-channel';
var socket = new window.Firebase('https://chat.firebaseIO.com/' + channel);
socket.channel = channel;
socket.on('child_added', function (data) {
var value = data.val();
if (value == 'joking') config.onopen && config.onopen();
else config.onmessage(value);
});
socket.send = function (data) {
this.push(data);
};
socket.push('joking');
this.socket = socket;
return socket;
};
Other Signaling resources
- XHR for Signaling
- WebSync for Signaling
- SignalR for Signaling
- Pusher for Signaling
- Firebase for Signaling
- PubNub for Signaling
transmitRoomOnce
transmitRoomOnce
is preferred when using Firebase for signaling. It saves bandwidth and asks DataChannel.js library to not repeatedly transmit room details.
channel.transmitRoomOnce = true;
Browser Support
DataChannel.js works fine on following browsers:
| Browser | Support | | ------------- |:-------------| | Firefox | Stable / Aurora / Nightly | | Google Chrome | Stable / Canary / Beta / Dev | | Android | Chrome Beta |
License
DataChannel.js is released under MIT licence . Copyright (c) Muaz Khan.