Adding chat functionality to website - javascript

I've been able to add chat functionality to my website but I'm wondering if there is a more efficient way to do it. This is the current structure of the chat:
HTML page with javascript functions:
sendChat(elmnt) {
var result = XHR("http_sendChat.aspx","POST",0,elmnt); //xmlhttprequest to send chat message by posting elmnt string to page. 0 used for not polling
}
getChat() {
var result = XHR("http_getChat.aspx","GET",50,""); //polls page every 50ms to get new chat messages
addMessageElmnt(result); //update chat window with new messages
}
On the server side in vb.net http_sendChat.aspx:
Application.Lock
Application("chat") = Application("chat") & Request.Form("message") //Global application object stores chat log
Application.Unlock
On the server side in vb.net http_getChat.aspx:
Dim chatTemp
chatTemp = Mid(Application("chat"),Session("chatIndex")) //fetches whatever chat data hasn't been fetched yet
Session("chatIndex") = Session("chatIndex") + Len(chatTemp) //set index to last read position
Response.Write(chatTemp)
There is some more code that mostly checks to make sure the users account is activated and such but as far as the chat goes, is there a better way to do this? I ask because its fairly slow when there are like 100 people logged in and using the chat.

Related

Will running jQuery.get too often cause performance issues for the browser?

So you understand what I'm trying to do, I've written a web page which shows events logged in MySQL as soon as they are inserted into the database (basically monitoring Windows & Mac logon/logoff on the network). Every time a new event is inserted the PHP script connects to a web socket and sends a message to all connected browsers to notify them of the new event. When the browsers receive the notification message they run jQuery.get("liveeventsearch.php", ...); to fetch the new event from the database (see javascript code below).
In a nutshell, when a web socket message is received fetch the new record from the database, append the result to a table and play a notification sound.
socket.onmessage = function(msg) {
if (msg.data == "#all new event") {
var newLastUpdate = new Date().toISOString().slice(0, 19).replace('T', ' ');
jQuery.get("liveeventsearch.php", <?php echo '{ Key:"' . $Value . '", etc... , lastupdate:lastUpdate }'; ?>, function(result) {
jQuery('#LiveResults tbody').append(result);
if (jQuery('#chkNotification-Audio').is(':checked') && result > "")
{
jQuery("#Notification-Audio").trigger("play");
}
lastUpdate = newLastUpdate;
});
}
};
My concern is that there are currently approx 1200 devices on the network and it is expected that most, if not all of them will logon/logoff within a 5 to 10 minute period in large clumps hourly with a few additional scattered here and there. So the browser (depending on the supplied search criteria) will likely receive a large number of web socket messages in a small period of time, if not simultaneously (and obviously fetch liveeventsearch.php that many times). Is this likely to cause a problem for the browser fetching results so frequently?
I can provide the code in liveeventsearch.php if necessary.
Alternate Methods
I had thought about adding something like this in the socket.onmessage function to reduce the frequency.
//[PSEUDO CODE]
if (currentTime > lastUpdate + 3 seconds)
{
jQuery.get(...);
}
But then the last set of events will not appear until another web socket message is received which could be a lot longer than 3 seconds. I could possibly use a timer instead, but that kind of defeats the object of having a web socket providing 'live' updates.
Another option I thought of is to create a new MySQL table (e.g. liveUpdates) which contains only an ID field. Then run a cron job every X seconds which inserts a new ID in that table (or run a a script on the server with a continuous loop doing the same thing?). My events table could then have an additional field tying each event to the latest liveUpdates.ID and the cron job could send the web socket message each time a new update ID was created instead of every time an event is logged. But this again would have the same effect as using a timer.

WebExtension: How can I access the background script in my browser action

I'm totally new to WebExtension (trying to use them under Firefox). I've written a browser action. In order to keep a persistent state I figured that I have to implement a background script.
How can I acccess variables defined in the background script from my browser-action script?
Or is the assumption wrong that the background script can contain the state for the browser action?
Ok, got it. I found a good start here and here.
I use message posting for communication between my browser-action and background script.
Think of a game where you can act in the browser action popup and the game state is in the background script. Here is an example for getting number of coins (player money) from the background script to the browser-action:
browser-action:
var _playerCoins = 0;
// I connect a 'port' with the name 'getCoins'.
var _port = chrome.runtime.connect({name: "getCoins"});
// This is the message that is called if the other side posts a message via the port.
// The background script puts the current amount of coins into the message
_port.onMessage.addListener(function(msg) {
// Save the number of coins in a local variable
_playerCoins = msg;
// Display number of coins on my browser action html page
document.getElementById("coins").innerHTML="Coins: " + _playerCoins;
});
background script:
// Add a listener for port connections
chrome.runtime.onConnect.addListener(function(port) {
// If there is a 'getCoins' connection coming in...
if(port.name == "getCoins") {
// ...add a listener that is called when the other side posts a message on the port.
port.onMessage.addListener(function(msg) {
port.postMessage(_playerCoins);
});
}
}

simpleWebRTC with php backend

I am using simpleWebRTC with xhr to implement peculiar multi-users video chat (no audio)
my main issue in short: i was unable to attach the username from php to the correct video in JS
in my quetion i will
1. explain what i have done - and what are my current issues
2. if my current route is impossible - then i ask for suggestions for a different course of action on my part :-) - my knowledge is in JS and PHP|
the multi-users video allows to chose a few users and see them in a one way connection.
lets say we have users A, B, C, D
user A chooses to see users B, C, D while user B for example only chooses to see users C and D .... and so on
in simpleWebRTC i thought of two courses of action
a. one room for all of the participants and then to filter them down (was unsuccessful as i was unable to attach the correct username to each video - to filter them out)
2. instead i created a room (with username - email, as id) and let each user connect to the appropriate room.
in the first part of the code i have an XHR that pulls a list of the people the user wishes to subscribe to there videos (i.e: chooses to see)
var remoteRoom = [];
$.get('scripts/video/ours/musesSimpleList.php', function(msg){
myRoom = msg.username;
var remoteRoomArray = $.each( msg.museUsername, function(key, value){
remoteRoom.push = value;
return remoteRoom;
});
afterRoomDefined(myRoom, remoteRoomArray);
}, 'json');
function afterRoomDefined(myRoom, remoteRoomArray) is called after the list of people this specific user chose to register to was retrieved from MySQl
in this function, i now try to implement the WebRTC:
function afterRoomDefined(myRoom, remoteRoom){
console.log('remote room name: '+ remoteRoom + ' type: '+ $.type(remoteRoom));
remoteRoom = JSON.stringify(remoteRoom);
console.log('isArray '+$.isArray(remoteRoom));
//Create our WebRTC connection
var webrtc = new SimpleWebRTC({
url:'https://signaling.simplewebrtc.com:443',
//the element that will hold the local video
localVideoEl: 'localVideo',
//the element that will hold remote videos
//remoteVideosEl: 'remotes',
remoteVideosEl: '',
autoRequestMedia: true,
media: {
video: true,
audio: false
},
});
webrtc.mute();
// a peer video has been added
var i = 0;
//When it's ready and we have a room from the URL, join the call
webrtc.on('readyToCall', function(peer){
//each user first creates a room for himself - so other users could connect to
if(myRoom) webrtc.joinRoom(myRoom);
//here a room is created for every person the user subscribed to. each person created a room with his own username (when he opened this page in his browser) - in the line above. so now i open rooms with the same names - so the users will see each other (two ways now)
for(var b=0; b<remoteRoom.museUsername.length; b++){
console.log('remoteRoom loop - separate values: '+ remoteRoom.museUsername[b]);
if(remoteRoom.museUsername[b]) webrtc.joinRoom(remoteRoom.museUsername[b]);
}
});
// a peer video has been added
webrtc.on('videoAdded', function (video, peer) {
var remotes = document.getElementById('remotes');
if (remotes) {
var container = document.createElement('div');
container.className = 'videoContainer'+i;
$(container).attr('data-username', remoteRoom.museUsername[i]);
i++;
container.id = 'container_' + webrtc.getDomId(peer);
container.appendChild(video);
// suppress contextmenu
video.oncontextmenu = function () { return false; };
remotes.appendChild(container);
//this is to remove the other party video - if a user only subscribed to another user - the other user is not
//$('#remotes div:not[data-username]').css('border', 'red 5px solid');
$('#remotes div:not[data-username]').remove();
}
i=i+1;
});
webrtc.on('videoRemoved', function (video, peer) {
var remotes = document.getElementById('remotes');
var el = document.getElementById(peer ? 'container_' + webrtc.getDomId(peer) : 'localScreenContainer');
$('#remotes div').css('border', '#F4171A 2px solid');
if (remotes && el) {
remotes.removeChild(el);
}
});
That's it. and that basically works.
There are three issues though:
a. when one of the users refreshes his page (usually navigate back an forth) his own video is added again (two videos of the same user now - one of them is frozen) to all the other users who watches him. perhaps its an issue with
webrtc.on('videoRemoved'...
b. when user A for example registers to user B... - if user C than subscribes to user A - he will see also user B
the main issue perhaps is:
c. i was never really able to attach the username to the right video under:
webrtc.on('videoAdded',....
$(container).attr('data-username', remoteRoom.museUsername[i]);...
in the main block code.
I used
$('#remotes div:not[data-username]').remove();
to find all videos without username and kick (videos who were duplicated and froze+the other side of the video if user A subscribed to user B and not vice versa so user B will not see user A and so that C will not see in the above explanation) them out - but the username it self is not attached to the correct child in the right order (the moment someone refreshes the page the order scrambles....
am i going the right direction?
i had a look at pubNub, xirsys, firebase and some other solutions
(google appengine - java knowledge required, html5Rocks, easyRTC, signalMaster (no proper explanation on how to use)- but it seems that they all require node.js )
is my current mode of action (php and XHR) is a valid one?
if not - will one of the other solution will be relatively simple and plausible.
I started looking through too many api's and am confused by now
thank you :-)
It's hard to see exactly what goes wrong, because you seems to face multiple issue here, including webRTC in general and DOM insertion/removal problems.
If you are seeking for webRTC solution using PubNub, you should take a look at:
https://github.com/stephenlb/webrtc-sdk
and the demo that you can try:
http://stephenlb.github.io/webrtc-sdk/
also, check out
http://www.pubnub.com/blog/building-a-webrtc-video-and-voice-chat-application/

Titanium - prevent exitOnClose from stopping the app

My app uses the gcm module to listen for notifications and displays android notifications for every new notification that comes in. Additionally, the current window gets updated with the new count of unread messages.
This window is created using Ti.UI.createWindow({exitOnClose:true})
The problem is, that when the user presses the back button, the application stops. This means, I don't receive any more notifications and thus cannot display them in the notifications bar.
Is there a way to make titanium hide the app when pressing the back button, but not stop it, so that my code stil is running in the background?
I know of the possibility to start a service, but the downside of this is that i cannot update my window, when it's currently visible to the user, since there seems to be no way to communicate between the service and the app. Or is there a way?
app.js
//this is the most important line in this code.
//if I do exitOnClose:true, I stop receiving notifications every 5 seconds when pressing the back button (not good!, I want to keep getting notifications)
//if I do exitOnClose:false, I go back to a blank, "powered by titanium" window, when pressing the back button (not good!, I want the app to go to the background)
var win = Ti.UI.createWindow({exitOnClose:true});
//not part of the question
var label = Ti.UI.createLabel({text:"0"});
win.add(label);
win.open();
var notifications = [];
//listen for notifications (not part of the question)
listenForNotifications(function(notification){
//handle the notification
notifications.push(notification);
//update window
label.text = "Notification Count: "+notifications.length;
//display notification in title bar
displayNotificationInTitleBar(notification);
})
//this function is just dummy code to simulate listening for notifications in background using the gcm module
//it simulates a new notification every 5 seconds with an always increasing id
//it actually does not matter what module I use for notifications, Just take it as given that there runs code in the background,
//that I don't want to stop, after the user taps the backbutton
function listenForNotifications(cb){
var i = 0;
setInterval(function(){
cb({id:i++});
},5000);
}
//This function is actually not part of the question, it's just a sample
function displayNotificationInTitleBar(notification){
var intent = Ti.Android.createIntent({
action: Ti.Android.ACTION_MAIN,
packageName:"com.company.backgroundnotificationstest",
className:"com.company.backgroundnotificationstest.BackgroundnotificationstestActivity",
flags:Ti.Android.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | Ti.Android.FLAG_ACTIVITY_SINGLE_TOP
});
intent.addCategory(Ti.Android.CATEGORY_LAUNCHER);
intent.putExtra("notificationid",notification.id);
Titanium.Android.NotificationManager.notify(notification.id, Titanium.Android.createNotification({
contentTitle: "New Notification",
contentText : "ID: "+notification.id,
contentIntent: Ti.Android.createPendingIntent({
intent:intent,
type : Ti.Android.PENDING_INTENT_FOR_ACTIVITY
}),
flags : Titanium.Android.ACTION_DEFAULT | Titanium.Android.FLAG_AUTO_CANCEL | Titanium.Android.FLAG_SHOW_LIGHTS
}));
}
The sample app is available at: https://github.com/VanCoding/TitaniumBackgroundNotificationsTest
Feel free to compile it and see it yourself :)
Since you set exitOnClose your app will exit on closing the window you have created. To prevent exiting from the app you need to reset the key as follows while creating the window.
Ti.UI.createWindow({exitOnClose: false});
If you would like to show the notifications in the notifications tray, make sure that you have set the following keys
showTrayNotification
showTrayNotificationsWhenFocused : This will display the notification in the tray even when the app is focused.
To show/hide a badge, you can try the following tip.
You need to keep track how many notifications you received and you need to update it upon receiving the notification. Just update the badge using the value stored. I tried this solution and is working great in one of my app
After a bit of thinking, I came to the following (a bit hacky) solution:
win.addEventListener("android:back",function(){ //listen for the back-button-tap event
e.cancelBubble = true; //prevent the back-button default action
//display the home screen
var intent = Ti.Android.createIntent({
action: Ti.Android.ACTION_MAIN,
flags:Ti.Android.FLAG_ACTIVITY_NEW_TASK
});
intent.addCategory(Ti.Android.CATEGORY_HOME);
Ti.Android.currentActivity.startActivity(intent);
});

Handling browser window close in a nowjs chat application

I am creating a chat application with nowjs.User can create a chatroom and then invite users to that room.Following is the code used to do this:
everyone.now.addPeopleToChat = function(clientIds,roomName) {
var length = clientIds.length;
var group = nowjs.getGroup(roomName);
for(var i=0;i<length;i++){
group.addUser(clientIds[i]);
}
group.now.roomName = roomName;//User can be in one room only at any given time.Reference to the roomname to be used when user leaves chat
group.now.loadChatWindow();//Load UI
}
So far so good.Users are able to be added to chat room and chatting is also fine.
When a user is in a chat room and he closes the browser window,I want other users in the chat room to be made aware that this person has left the chat.I thought of using the disconnect event to handle this particular situation.This is the code I have used.
nowjs.on('disconnect', function () {
console.log("User name:"+this.now.name);//comes fine
console.log("Room name:"+this.now.roomName);//shows undefined.
var group = nowjs.getGroup(this.now.roomName);//Intention is to get the room in which user was chatting.But it is not working because roomName is undefined.
group.now.broadcast(this.now.name+" has left this room");
});
Why is that roomName is shown as undefined in disconnect handler.I am setting that variable when the users are added to the group right.So each of the user in the group should have that variable set right.Am I missing something here?

Categories

Resources