How to set up an online chat without javascript? - javascript

I stumbled upon a rather strange site the other day : https://harmless.herokuapp.com/main
It is an online mini chat that does not use javascript on the client side, and yet it allows you to display your messages and those of others, in real time.
While trying to document myself I came across the term "Long Polling" but all the sources I could look at used javascript to implement it.
I guess the forever loading page is something to do with it.
From what I understand, if a valid XMLHttpRequest is not returned, then the client-side browser never closes the connection with the server and keeps trying to receive data.
I tried the code below but it didn't work : How do I implement basic "Long Polling"?
<?php
if(rand(1,3) == 1){
/* Fake an error */
header("HTTP/1.0 404 Not Found");
die();
}
/* Send a string after a random number of seconds (2-10) */
sleep(rand(2,10));
echo("Hi! Have a random number: " . rand(1,10));
?>
In short, I wanted to understand how a site could update the data received and send it back to the user in real time without using client-side javascript.
EDIT :
Here is the answer : github.com/kkuchta/css-only-chat
Thank you to Flux for his find!

Related

Determine Signal R connection status without broadcasting Clients.All.someMethod() and blowing up client side resources

I'm concerned about using Clients.All in my C# Signal R hub class
Clients.All.setConnectionStatus(profileId, true);
I'm calling it in both OnConnected() and OnDisconnected(bool stopCalled)
to show the online status of my logged in users.
OnDisconnected() isn't as bad because it's only being called when someone actually logs off
ex.
public override Task OnConnected()
{
string profileId = Context.User.Identity.Name;
_connections.Add(profileId, Context.ConnectionId);
Clients.All.setConnectionStatus(profileId, true);
return base.OnConnected();
}
public override Task OnDisconnected(bool stopCalled)
{
string profileId = Context.User.Identity.Name;
_connections.Remove(profileId, Context.ConnectionId);
if (stopCalled == false) // log off only
Clients.All.setConnectionStatus(profileId, false);
return base.OnDisconnected(stopCalled);
}
My concern -> Blowing up the users machine client side with javascript code constantly running in the browser!
Scenario -> If I have > ~1000 users online and logged in traversing to different pages, I will be broadcasting to all of them a signal R connection Clients.All.setConnectionStatus(profileId, true);
which in the javascript hub looks like this below which could easily end up blowing up the users browser, because it would be constantly receiving these broadcasting connection status calls!!!
scope.chat = $.connection.chatHub;
// Receive and set the connection status
scope.chat.client.setConnectionStatus = function(profileId, isConnected) {
// look for prfileId in html
var $profileStatusElement = $(".online-status-profile[data-id='" + profileId + "']");
var $profileChatElement = $(".online-status-chat[data-id='" + profileId + "']");
if (isConnected === true) {
// change the online status
} else {
// change the online status
}
};
I have chat windows to users (online) like below that shows a users status next to their name. So I know if the person I'm sending a message to is online or not!
When I first load the chatbox, I fetch the online status server side, but after that it's up to the OnConnected() and OnDisconnected() methods in my hub to set the online status of the person I'm chatting with.
There's got to be a better way then broadcasting the signal out to 'all' online users on my site? But the only way I can think of is to poll the status every so often on some javascript timer, but I hate that idea!!
Another way would be to keep some kind of in-memory collection of who each person is chatting with, but that seems like it could get really messy and could end up up not being very accurate, being there could be so many things in between the client and server that could cause a disruption to mismanage the in-memory collection of who's connected to whom! Any thoughts or ideas here would be greatly appreciated!!
FYI -> I also have a messages page, that shows a list of all the recent conversations I've had with users like below. And on this page I show the online status of these users as well. On this page I fetch the online status of each user on the server before I render the page, same as the chat box, but once the page is loaded, it's up to the OnConnected() and OnDisconnected(bool stopCalled) to set the online status of each user on the page.
You're doing in right way with signalR. I guide you based on your concerns/scenarios:
My concern -> Blowing up the users machine client side with javascript
code constantly running in the browser!
Don't forget that you are using a browser underlying functionality (WebSocket), so we have no choice unless running some js code inside client loaded page. You take advantage of browser capabilities here.
Scenario -> If I have > ~1000 users online and logged in traversing to
different pages, I will be broadcasting to all of them a signal R
connection Clients.All.setConnectionStatus(profileId, true);
Before proposing any solution, I exhort you to employ grouping logic in your application. Grouping reduces the volume of synchronizations.
If you working on a public chat room (which can contain large number of people), by employing server side strategies simply you'll make your code to a dirty one! Yes, Any user who navigates or refreshes the page can cause a redundant update to all the clients. Best Solution is turning you page to SPA (working with API call or Ajax call) with no page refresh. I believe that any real-time web application should take advantage of modern web technologies. This will solve almost every problem which you suffer (e.g no page refresh, no reRun, no disCoennection & etc ...).
Solutions like using a js timer to fetch latest status for users is not clean or desirable.

display number of message dynamically using javascript or asp.net

I will do my best to explain my problem to avoid people pointing me into different directions.
I got an assignment from business people. I don't know the terminology. It is very similar to email notification, message notification on facebook, notification on social media games.
For example, people are sending 20 email messages 5 minutes ago. the screen will display 20 (see attachment). Now, 3 more messages have arrived, the web page should update the number to 23.
Facebook has similar concepts when our friends like/comment message. The notification changes. Same thing is true on social media game. Any status changes on our game, it will reflect it.
I kind of have idea on how to do it cosmetically (on CSS). How to do it using javascript/asp.net. Do I need to postback in order to refresh the message. I never pay attention to that on facebook/yahoo email/social media games. All I know is something is happening, the webpage is updating the status.
Sorry the question is too broad. If someone can help me to point to the right direction, I appreciate any help
HTML5 introduced a very interesting concept call Server-Sent Events in which server can dynamically connect to the client and send data.
Eg:
var source = new EventSource("demo_sse.asp");
source.onmessage = function(event) {
document.getElementById("result").innerHTML = event.data + "<br>";
};
And on server side you can write,
<%
Response.ContentType = "text/event-stream"
Response.Expires = -1
<!--Writing "data:" is important-->
Response.Write("data: The server time is: " & now())
Response.Flush()
%>
However, some old browsers may not support this.
One other way to accomplish this task is to use Ajax call as,
function checkNewMessages(totalMessages){
return $.ajax({
url: 'demo.asp',
type: 'GET',
cache: false,
data: {
totalMessages: totalMessage;
}
});
}
checkNewMessages(totalMessages).success(function (data) {
// display the data wherever you want
});
//Checking for new messages every 5 seconds
setInterval(checkNewMessages(totalMessages,5000));
Whatever you write within your Write() in server side will be displayed here. Now to constantly check for the new messages you can call the above ajax function with the help of setInterval()
There are many ways to do this, depending on how real time you need it to be.
The most common way is to use JavaScript with an XmlHttpRequest to call an ASP.NET page which returns the number of messages, I recommend you use a JSON object for this. The benefit of this approach allows you to request data from the server without the user experiencing a full page refresh. You can use JavaScript to set it to call every x seconds depending on your requirements.
Collectively that is known as AJAX, using a JavaScript library such as JQuery can make this much easier.

How to share data between clients using JavaScript?

I have a variable for JSON, but I want to make it where everyone that is on that PHP Page will be able to see the same variable contents.
This code should explain more of my situation.
(I am trying to make it where the page won't reload)
var chats = [];
var j = jQuery.noConflict();
j(document).ready(function()
{
setInterval(function(i){
var txt = "";
var x;
for (x in chats) {
txt += chats[x] + " <br />";
}
document.getElementById("json").innerHTML = JSON.stringify(chats);
}, 1000)
});
j(document).ready(function() {
j('#post_button').click(function() {
$text = $('[name=message]').val();
$sender = $('#texta').val();
chatstuff = {
"sender" : $sender,
"message" : $text,
};
chats.push(chatstuff);
$('[name=message]').val("");
});
});
So when it does document.getElementById("json").innerHTML = JSON.stringify(chats);, I want everyone to be able to see the same chats content when they are on the same page.
JavaScript runs in the user's browser. Any data in a variable is only visible to that client.
In order to synchronize data between clients, you would need to use something like websockets. Each client (user) would send data to your server and the server would relay all client activity to each client.
A very popular JavaScript websockets library is socket.io. You'll find a plethora of "How to create simple chat in JavaScript with websockets" tutorials if you just start searching for them.
Here's a socket.io chat demo that's right on there site.
"Why use websockets instead of Ajax?"
Well, just think about it for a little bit... Ajax is great for clients sending data to the server asynchronously, but what about the server talking to the client?
If user A writes "hello", we can send that to the server using Ajax, but how will users B and C be notified that a new message arrived?
Historically, before websockets, this was done with Ajax "long polling". What that means is each client will make an ajax request to the server every x seconds that asks "Hey, any new messages for me to read?"
If you're implementing a realtime chat app, that means x is going to be something like a max of 5 seconds otherwise users will be too frustrated with the lag.
Pinging our server every 5 seconds to ask the same question over and over is annoying. And it's quite archaic by today's standards. Maybe there's a better way...
"OK, so how does websockets make this better?"
Well websockets allows a connection between the client and server to stay open. This means that the server can send data to the client as soon as data arrives, without the client having to ask for it.
This means that we can ditch the polling and get data sync'd up even faster! Sweet!
"OK, that's great, but I can't rely on bleeding edge technologies..."
Well that's not really a problem either. The reason I recommended a websocket lib (e.g., socket.io) is because the socket.io will make a wide variety of attempts to achieve a socket-like connection in the event that your browser doesn't support actual websockets.
Included in a list of fallback methods is none other than... drumroll, please... Ajax long polling.
"Is there any alternative to socket.io?"
Yep. Now that you know you're looking for it should be easy to find tons of options out there. ws is another great lib that i'd definitely check out if socket.io seems too heavy-handed for you.
no, you have to use a server for this. send new data from this page to the server and the server will update the page for other viewers. consider reading some tutorials like this http://tutorialzine.com/2010/10/ajax-web-chat-css-jquery/

Best way to prevent a user clicking 'like' multiple times

I'm implementing a like feature for a site I'm working on. A user doesn't have to be logged in and they can either like or dislike a particular page. At the end of it all I'd like to be able to populate a list of articles or stories with the most likes.
I have a very simple method that currently uses an onclick javascript function to update a database via ajax and a php function.
This is working ok. What I'd like to do is prevent a user from spamming the button.
At first I thought of maybe getting the IP address, storing that in the database and then running a check. Is there a better way?
Technically there isn't a bomb proof way to do so. You could get pretty close by allowing one vote per ip-useragent combination. You'd have to implement this on the server side.
PHP Example
$concienceKey = md5($_SERVER['REMOTE_ADDR'] . $_SERVER['USER_AGENT']);
$query = "SELECT COUNT(*) FROM clickConcience WHERE key = `" . $concienceKey . "`";
//run your query
//.....and get the $count;
//
//already voted!
if($count > 0){
echo 'already voted';
return false;
}
//remember entry
$insert = "INSERT INTO clickConcience (key, datetime) VALUES (`" . $concienceKey . "`, NOW())";
//run your query
//.....and insert
//
return true;
straight forward answer, you won't be able to do it.
If I really want to SPAM your "like" button, I will find a way to do so, especially if you're not forcing me to be signed in (I used to write pretty good bots and were pretty efficient spamming big link submission sites).
Javascript will only stop mediocre spammers or sock puppet account holders. As a spammer I can circumvent your Javascript pretty easily, either by programming a time-based robot to like your post, or by sending requests directly to your server (I will not even load your site).
What you need to do, if you really want to prevent spammers from spamming this feature efficiently (efficiency is the keyword here because spammers can still spam your feature, but their likes won't count) is to log every IP that likes a post along with its geographical information (it's not always 100% accurate, but it's a good start) and then run a process in the background that checks for suspicious origins and penalize such likes (either by assigning them less value, or just subtracting them from the total count).
For example if your main audience is people living in the United States, but one post gets a bunch of likes from Mexico, Salvador, India, Australia, Russia, then it's more than likely that there's a spammer behind a proxy or a network similar to TOR and he/she can change his/her IP address at his/her will.
After a few hundred thousand records, you'll have a good base to start blacklisting IP addresses. I usually use R programming language to get statistical information about my databases.
But then again, a good spammer could use a list of IP addresses of compromised computers coming from your audience's country or geographical location, and use those IPs to abuse the feature. Those bots are harder to spot, but you can analyze previous posts and come up with useful metrics as "Likes/comment ratio".
If one post has a huge number of likes, but low number of comments, then it's very probable that someone spammed it, but then again I can program my bot to like AND post a comment so the numbers look natural.
I'm not sure what kind of project you're working on, but if it's something similar to link submission, do not rank (whatever your users are liking) by the number of likes.
The number of likes should only be a factor, you can take a look at how HackerNews or Reddit rank the posts (those projects are open source), but it's a combination between multiple factors.
Just hide the button after it has been clicked for the first time.
It does even makes more sense, when using an AJAX handler for sending the click...
Use cookies. Lets say you have a button where the user can like article 123456789
<button id="like" articleID="123456789">Like</button>
script :
function setLike(articleID) {
document.cookie=articleID+'=y';
}
function hasLiked(articleID) {
var cookies=document.cookie.split(';');
for (var i=0;i<cookies.length;i++) {
var cookie=cookies[i].split('=');
if (cookie[0]==articleID) return true;
}
return false;
}
var button=document.getElementById('like');
button.onclick=function() {
var articleID=this.getAttribute('articleID');
if (!hasLiked(articleID)) {
//register the like in your system
//...
//
setLike(articleID);
} else {
alert('You cant like or dislike an article twice');
}
}
Of course the user can delete all his or hers cookies - but a user can also like the same page / article from 100 different computers. The above prevents the most common scenario : People repetetively clicking like or dislike a lot of times from the same computer in a short distant of time.

Best practice for a practical real-time app with .NET MVC4

Hello people and bots,
I'm developing the front-end web application for a system and have hit a little problem.
The whole application has to be on one page, meaning no refreshes or page changes during the flow of the major areas of the application.
It also has to work in all web browsers including IE7 and be deploy-able as a HTML5 application for tablets and mobile phones.
It's based around a user logging in, which is regulated by webforms authentication, then I need to poll or long-poll the server for updates. This would be simple if I could do a request for each part of the system, however if the system gets too big session blocking becomes a problem and it could also end up ddosing itself. So what I need to do is think of a way to send one request and build one response from that request.
My first idea was to build a response model with JSON or XML and let JavaScript regulate what needs to be updated. For example, a new comment has been made on a topic, all the clients see this update near instantly. My idea was to send something like this:
[
'd':
{
'addComment' : [{'topicId':'topic1', 'description':'haha'}, {'topicId':'topic1', 'description':'lol'}],
'addTopics' : ['topic2','topic708'],
}
]
JavaScript would then parse this and add "haha", and "lol" to the element with the id "topic1". In theory it seems quite simple to achieve, but as the system is getting bigger it seems to constantly be turning into a big mess.
My second idea was to simply have a set of client-side functions for adding and removing stuff in the DOM, And then use a JSONP technique to call this function.
var addComment = function(commentModel)
{
var topic = document.getElementById(commentModel.topicId),
comments = topic.getElementByClassName('comments')[0],
comment = document.createElement('div');
comment.innerHTML = commentModel.description;
comments.appendChild(comment);
updateUnreadComments();
}
Response:
(function(addComment){
addComment({ topicId : 'topic1', description : 'haha' })
addComment({ topicId : 'topic1', description : 'lol' })
})(addComment)
Personally I find both methods a rather annoying workaround for nothing more than simple broadcasting.
I was wondering if anyone else has ever had the same problems and if they have ever come up with a more creative solution.
I would also like to know what kind of security issues I could expect with JSONP.
All help is appreciated!
You may take a look at SignalR. Scott Hanselman also blogged about it.

Categories

Resources