Skip to content

Instantly share code, notes, and snippets.

@ajaxray
Last active July 18, 2022 09:57
Show Gist options
  • Save ajaxray/17d6ec5107d2f816cc8a284ce4d7242e to your computer and use it in GitHub Desktop.
Save ajaxray/17d6ec5107d2f816cc8a284ce4d7242e to your computer and use it in GitHub Desktop.
Keep list (and count) of online users in a Firebase web app - by isolated rooms or globally

Gathering.js - Overview

Keep list (and count) of online users in a Firebase web app - by isolated rooms or globally.

Let's create a new gathering

firebase.initializeApp({...});
var gathering = new Gathering(firebase.database(), 'A Room Name');

Now you'll have the following functions and properties to work with -

  • gathering.join(uid, displayName) - Add me to gathering. Optionally can provide a unique id and displayName.
  • gathering.leave() - Leave (that means remove myself from) the gathering
  • gathering.over() - Remove gathering from database
  • gathering.onUpdated(callback) - That function will be called (with user count and hash of users as param) every time the user list changed
  • gathering.roomName - The gathering name
  • gathering.myName - Current users's name in gathering, if joined
  • gathering.room - Firebase Database reference to the gathering room. Can be listened for removal or anything.

To see the usages in more details, please check the firebase-online-user-count-example.md file

Gathering.js - How to use

Keep list (and count) of online users in a Firebase web app - by isolated rooms or globally.

Live Demo

Firebase Shared Checklist is a demo application that shows the number of users joined a checklist using gathering.js. Here is a 1 minute screencast of using this application. You may have a look at the source code to see example usages.

Initialization

firebase.initializeApp({...});

// default/global gathering
var onlineUsers = new Gathering(firebase.database());

// Create an isolated space
var chatroom = new Gathering(firebase.database(), 'Special Name');

Joining, Leaving and Ending (removing) a gathering

var gathering = new Gathering(firebase.database(), 'Gathering Name');

// Join Anonymously
gathering.join();

// Or Join with a unique id
// This will ensure distinct presense of a user, even if opened on multiple browser tab or device
gathering.join(firebase.auth().currentUser.uid);

// Also can set a display name (along with or without unique id)
gathering.join(null, 'Superman');
gathering.join(firebase.auth().currentUser.uid, 'Superman');


// When I am finished with the gathering, I may leave
// When browser is closed/refreshed, current user will automatically leave 
gathering.leave();

// When all user's have left, or the meetup is over, we can remove the gathering
gathering.over();

Let's do something with the user count and user name list

var gathering = new Gathering(firebase.database(), 'Gathering Name');

// Attach a callback function to track updates
// That function will be called (with the user count and array of users) every time user list updated
gathering.onUpdated(function(count, users) {
    console.log(gathering.roomName + ' have '+ count +' members.');
    console.log('Here is the updated users list -');
    for(var i in users) {
        console.log(users[i] + '(id: '+ i + ')');
    }
});
/**
* A Javascript module to keep list (and count) of online users in a Firebase web app - by isolated rooms or globally.
*
* Initial idea from - http://stackoverflow.com/a/15982583/228648
*
* @url : https://gist.github.com/ajaxray/17d6ec5107d2f816cc8a284ce4d7242e
* @auther : Anis Uddin Ahmad <[email protected]>
*
* w:ajaxray.com | t:@ajaxray
*/
var Gathering = (function() {
var randomName = function () {
return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5);
};
function Gathering(databaseReference, roomName) {
this.db = databaseReference;
this.roomName = roomName || 'globe';
this.room = this.db.ref("gatherings/" + encodeURIComponent(this.roomName));
this.myName = '';
this.user = null;
this.join = function(uid, displayName) {
if(this.user) {
console.error('Already joined.');
return false;
}
this.myName = displayName || 'Anonymous - '+ randomName();
this.user = uid ? this.room.child(uid) : this.room.push();
// Add user to presence list when online.
var self = this;
var presenceRef = this.db.ref(".info/connected");
presenceRef.on("value", function(snap) {
if (snap.val()) {
self.user.onDisconnect().remove();
self.user.set(self.myName);
}
});
return this.myName;
};
this.leave = function() {
this.user.remove();
this.myName = '';
};
this.over = function () {
this.room.remove();
};
this.onUpdated = function (callback) {
if('function' == typeof callback) {
this.room.on("value", function(snap) {
callback(snap.numChildren(), snap.val());
});
} else {
console.error('You have to pass a callback function to onUpdated(). That function will be called (with user count and hash of users as param) every time the user list changed.');
}
};
}
return Gathering;
})();
@jose2007kj
Copy link

sir,i am planning to store user registration details in firebase,so can i use your code to find number of users registred
thankyou sir

@ajaxray
Copy link
Author

ajaxray commented Nov 15, 2016

@jose2007kj you are welcome. Of course you can.

But, I guess, you do not need this module for just counting registered users. You can get the count just by numChildren() function on your user collection.

@w1f7UBC
Copy link

w1f7UBC commented Oct 20, 2017

Can anyone recommend a module or github page for the tracking of all users including ones that are not currently online? All users that have ever registered. I would like to get a count of all users or a list.

@bizstudio
Copy link

Thank you.
this library is very useful!!
however, I have one issue using this in ionic.

ERROR TypeError: Cannot read property 'remove' of null
at Gathering.leave (gathering.js:49)
at HomePage.webpackJsonp.92.HomePage.logout (home.ts:114)
at Object.eval [as handleEvent] (HomePage.html:9)
at handleEvent (core.js:13589)
at callWithDebugContext (core.js:15098)
at Object.debugHandleEvent [as handleEvent] (core.js:14685)
at dispatchEvent (core.js:10004)
at core.js:10629
at HTMLButtonElement. (platform-browser.js:2628)
at t.invokeTask (polyfills.js:3)

how can i fix them?

@librallaw
Copy link

I don't know if I will get an answer to this but let me ask hoping that I do

Thank you for this awesome library, I am faced with an issue of the online users duplicating after a page refresh.

When a user logs in, the count is accurate and online users too are accurate but when one of the users logs out or closes his/her browser, the users that are still logged in can see the count reduce by 1 but the logged out user name still appears.

Let assume, I have the following list as online users;
User1
User2
User3

After User1 closes the tab, this is what I would have;
User1
User2
User3
User2
User3

Any help would be appreciated, I tried modifying the code to something like this;
let unique_users = array_unique(users);
for(var i in unique_users)
but I am still getting the same results.

but I still get the same result.

@Neat-Coder23
Copy link

Sir, is there a cdn link to this library to connect from client-side???

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment