I have an html5/javascript application in which multiple users can be viewing the same set of data of any given time. For the sake of a real world example, lets say its a calendar type page.
So user1 is looking has the browser open and looking at the calendar page and user2 is also on the calendar page. User2 makes a change to the calendar and i'd like (as quickly as possible) for those changes the be recognized and refreshed on user1's screen. What is the best way to do this?
I'm thinking about have a mysql table for active users that stores the page they are currently on and a timestamp for its last update, then use ajax calls to ping the server every few seconds and check for an updated timestamp, if its newer than what they have client side, the new data gets sent and the page "reloaded." I am putting reloaded in quotes because the actual browser window will not be refreshed, but a function will be called via javascript that will reload the page. Sort of the way stack overflow performs its update checks, but instead of telling the user the page has changed and providing a button for reload, it should happen automatically. If user1 is working away on the calendar, it seems it might be quite annoying for user2's screen to constantly be refreshing...
Is this a horrible idea? Is pinging the server with an ajax request every few seconds going to cause major slow downs? Is there a better way to do this? I would like the views on either users side to be real time because its important that user1 not be able to update an element on the calendar page that user2 has already changed.
Update: based on some web sockets research it doesnt seem like a proper solution. First its not compatible with older browsers and i support ie8+ and second i dont need real time updstes for all users on the site. The site is an account based applicatiin and an account can have multiple users. The data needs to sync between those users only. Any other recommendations would be great.
You need realtime app for this. You should have a look at socketio. Everytime a user log in, you make him listen for changes on the server. Then when something changed on the server, every users listening are notified.
you can find examples on the official website : http://socket.io/
Related
I'm developing a website that is suppoused to control some devices that rotate when pushing one button. However, I only want one user at a time to be able to push the button.
That is, when a user enters the page, check if it is the "first" or only user that is there. In case he is, he can use the button freely. In case he isn't, the button appears as disabled.
What would be the best way to implement this? I'm using a classic design of html+js+php.
Thank you.
This is a design question, and still, you should have already tried something and post that something before asking here.
You should use a lock system:
create an endpoint with php, to call with Ajax that checks over a variable globally shared (better if on db) that acts like a semaphore, the first who arrive make it red and 'acquire the lock'.
If the lock is acquired, the client can do the action,
If the lock is not acquired, someone else took it already.
Do not forget to release the lock after the action.
You can use the same call to acquire the lock, do the action and release the lock. If the lock is not acquired the call return an error message and the user will know which is the issue.
P.S.
If you was thinking about a real time system, you may consider using websockets or just the system above with different calls for acquire the lock and do the action (and poll for the lock status).
To track a user on a website is not that difficult, but check if and when he/she leaves is the challenge.
If this is not time crucial you can do this with timeouts.
First, you need to be able to track the current user on your site (maybe with sqlite, textfile, mysql/mariadb) (maybe identified by IP) wich is updated a user loads the page.
After a timeout the tracking storage can be updated and the next or new one can hold the button.
If you need this realtime, you need a bit more to do. In this case I would use Websockets or NodeJS to keep connections to your page wich in fact you can use to keep track on active users and wich one should be able to keep the button.
Just keep it like a realtime online chat without texting. There you need to keep track of online users as well.
(Websockets or NodeJS are here only a example, there are alot technique to archive realtime "collaboration".)
I am creating a complex social networking website that is all one single page that never refreshes unless a user presses the refresh button on the browser.
The issue here is that when I edit files and upload them to the server they don't take effect unless the user refreshes the browser.
How would I go about and fix this problem? Should I do a time interval of browser refreshes? Or should I poll the server every 10 minutes to check if the browser should do a refresh?
Any suggestions?
Server
I would communicate the version number through whatever means you're already using for data transfer. Presumably that's some kind of API, but it may be sockets or whatever else.
Whatever the case, I would recommend that with each response - a tidy way is in the header, as suggested in comments by Kevin B - you transmit the current application version.
Client
It is then up to the client to handle changes to the version number supplied. It will know from initial load and more recent requests what the version number has been up until this point. You might want to consider different behaviour depending on what the change in version is.
For example, if it is a patch number change, you might want to present to the user the option of reloading, like Outlook.com does. A feature change might do the same with a different message advertising the fact that new functionality is available, and a major version change may just disable the site and tell the user to reload to regain access.
You'll notice that I've skated around automatic reloading. This is definitely not a technical issue so much as a UX one. Having a SPA reload with no warning (which may well result in data loss) is not the best and I'd advise against it, especially for patch version changes.
Edit
Of course, if you're not using any kind of API or other means of dynamically communicating data with the server, you will have to resort to polling an endpoint that will give you a version and then handle it on the client in the same way. Polling isn't super tidy, but it's certainly better - in my strong opinion - than reloading on a timer on the offchance that the application has updated in the interim.
Are you talking about changing the client side code of the app or the content? You can have the client call the server for updated content using AJAX requests, one possibility would be whenever the user changes states in the app or opens a page that loads a particular controller. If you are talking about changing the html or javascript, I believe the user would need to reload to get those updates.
I am building a WebApp (ERP) and I need to display the people currently logged in and active on the page. I managed to get something pretty accurate by listening on the mouse/keyboard events and periodically reporting to the DB.
I don't know how to mark people offline when they close the page. I tried using onbeforeunload, but it obviously fires when the user simply changes pages (click a link inside the ERP, that point to another page in the ERP).
I then tried to use WebSockets, but the problem is the same : everytime the page is realoded, the WebSockets connection is closed.
So I can think of two ways:
Use WebSockets indeed, and replace all links by a call to a javascript function that would somehow tell the server that the user is going to change page (so that the server doesn't mark it as offline). But that doesn't feel right, semantically speaking, links should be links, it simply points to another location.
Use either WebSockets or AJAX and never actually change page: links are replaces by a function that will call for the content, and display it on screen (updating the DOM with Javascript). But again, it doesn't feel right either, because semantically speaking the page would have no meaning and the URL would never change, so the user can't "copy paste" the link of the page to refer to it, right ?
So, is there a proper, clean way of doing this? Thanks for your help.
If each of your pages has a webSocket connection to your server, then on the server you can see when any given page is closed by seeing that the webSocket gets closed.
To avoid thinking that a user has left the site when they are just navigating from one page in your site to another, you simply need to add a delay server-side so that you only report that the user has left your site if there has been no webSocket connection from this user for some time period (probably at least a few seconds).
So, on your server when you detect that the last webSocket connection for this user has been closed, you set a timer for some number of seconds. If the user opens up another page on your site (either via navigation or just opens another page) before the timer goes off, you cancel the timer and count the user as still connected. If the timer goes off, then you now know that the user has been away from your site for whatever time period you picked (say 10 seconds) and to you, this will signify that they have left the site. You can control how long you want that time period to be before you decide that, yes they are gone.
All attempts at trying to "see" the user leaving your page IN the browser with Javascript are going to have holes in them because there are always ways for a web page to get closed without your client-side javascript having a chance to tell your server. The beauty of the webSocket solution is that the browser automatically and reliably tells your server when the page is now gone because it closes the webSocket and your server receives the notification that the socket has been closed.
As I understand you want to compute users active on website/pages.
Identify the user (99% unique id computed):
http://valve.github.io/blog/2013/07/14/anonymous-browser-fingerprinting/ you can use another library, there are few.
On each page send from time to time at page load meaning user is navigating or (60sec you can chose lower time frame meaning user is staing on the page) computed id (fingerprint js) to server (web-socket/ajax)
On server you need to have list of id's with expiration date (60s) increment when new user log's in (stored in database or session).
Retrieve on your website the count (60sec ajax/websocket) of id's having timestamp <= server time - let say 120sec.
Knowing if user is logged, and specify the page:
use an object to be sent at server {fingerprint: 123123124234, logged : true, page: home}
Clear your list if you are not storing in Database the users:
Separate thread (server only) access the object and destroy all nodes older then 10 min or whatever your page session is set.
js timer: http://www.w3schools.com/jsref/met_win_setinterval.asp
Let hope it's helpful, id did something similar using the timer at 5 min to sent to server if user is still on the page, or signal at page load.
Getting the cont of users in frame of 60 sec. And even the users with names present on page :)
Somebody already post this kind of question.
Hope this could help you .
Detect if user has closed ALL windows for a website?
I was tasked to build a calendar and agenda library (I'm working on the CodeIgniter framework), that shows a calendar and the user has the possibility to set events on that calendar.
These events will have a notification system both email, and when the user is browsing the site, a popup.
My issue is how to approach the notification part when the user is on the site. The email is something that I already decided would be done trough a cronjob that will run every x minutes and check if there is any need to send a notification email.
The on site notification is something else.
How would I approach this? I just can't make a ajax request to the server every x seconds, since that would put an unnaceptable load on the system. (Of course when the user is eventually notified, a request must be made, to set the user as "remined" on the database).
I can't just depend on the user's date time, since he could be anywhere in the world and the time would be different.
How can I check that the user must be notified of a event, avoiding making repeated requests to the server? Would appreciate any input.
I could see using setTimeout to do this. Say a user visits your page $minutesTilDue minutes prior the reminder being due. Assuming jQuery/PHP:
$(function(){
setTimeout(function(){
showEventReminder(<?php json_encode($event) ?>);
}, <?php echo $minutesTilDue ?> * 60 * 1000);
});
Nothing too fancy, but depending on your requirements...
Cheers
Easily scalable notification systems use websockets, which today reach the majority of the users, even on mobile devices. Unfortunately, you'll need a websocket-enabled server - node, glassfish, whatever - this can't be done with standard PHP deployments (mod_php or fcgi). Server events (so called server push) are sent when they are generated, so once you have your websocket client-server pair, sending a reminder is just like sending an email.
Actually things are more complicated because most likely users won't be online at the exact time the reminder should pop up. I suggest a notification icon which is refreshed each time the user hits a page. This way your calendar system (suppose a cronjob) will simply update a flag for the user row in the DB, and when you build the page, you already know if there reminders (let's say, in the next 60 minutes) or not, and choose the icon accordingly. At this point, you have two choices:
sending the reminders to the client along with each and every request (it could be a waste of bandwidth, but I don't thing a JSON-encoded list of events is so heavyweight)
Download the reminders asynchronously on demand, ie only when the user hits the notification icon
This scenario lets you reuse the PHP environment and code, and doesn't require another host for the websocket server. I think this is the best solution, even if this doesn't fulfill your requirement of a truly popup reminder triggered by the server at the right time. BTW, if you send events with every request, your javascript can pop up when needed - you can use setTimeout() for this.
I am quite new to web development and am working on this social networking site.
Now I want to add functionality to show if a person is online.
Now one of the ways I figure out doing this is by keeping online status bit in the database.
My question is how to do it dynamically. Say the page is loaded and a user (say connection) comes online. How do I dynamically change status of that connection on that page.
I wanted to know if there are any tools(libraries) available for this type of tracking. My site is in python using django framework. I think something can be done using javascript/ jquery . I want to know if I am going in the right direction or is there anything else I should look into?
Create a new model with a last_activity DateTimeField and a OneToOneField to User. Alternatively, if you are subclassing User, using a custom User in django 1.5, or using a user profile, just add the field to that model.
Write a custom middleware that automatically updates the last_activity field for each user on every request.
Write an is_online method in one of your models that uses a timedelta to determine a user's inactivity period to return a boolean for whether they are online. For example, if their last_activity was more than 15 minutes ago, return False.
Write a view that is polled through jQuery ajax to return a particular user's online status.
As Sanjay says, prefer using memory solutions (online statuses have a quite brief use) like the Django cache (Redis or Memcache).
If you want a simple way of updating the online status of an user on an already loaded web page, use any lib like jQuery, AJAX-poll an URL giving the status of an user, and then update the tiny bit of your page showing your wanted status.
Don't poll this page too often, once every 15 seconds seems reasonable.