How to signal a change in the post? - javascript

I was wondering how to reproduce the feature which is visible even on the StackOverflow page: when a user edits an answer for other users appear: "an edit has been made to this post; click to load". This is the functionality I am referring to:
https://meta.stackexchange.com/questions/125677/new-feature-real-time-updates-to-questions-answers-and-inbox
Basically, I have a function which takes some time to return the value, and once it happens I would like to update UI.

As they say in the post you are linking, only browsers that supports web sockets can use this feature. Read up on those, they are not too hard to use. It basically it enables the server to "push" data to the client. Be aware though that most servers doesn't support web sockets without extensions at the moment. Neither does all browsers.
Another solution would be to utilize an AJAX request, with setInterval or setTimeout, checking to see if new posts have arrived each i.e. 10th second. This will generate more http requests, but it should be more compatible. Also, it isn't true real time.

Related

Viewing javascript variable from any browser

I have variable in Javascript which are created by reading a number from HTML, adding a number to it and then returning it to HTML.
I want to make it so that no matter what browser/what user you are, you are seeing the latest version of the variable. Currently, if I refresh the page then the number resets to 0 (the default value). I want it so that if I update the number to 1 when someone else views it from another browser they will also see 1 and not 0.
I've seen that cookies are an option, however I thought cookies were client side only? So that would mean that only I would see the latest version of the variable.
I've seen that sessions are another option, are sessions server side? And would they do the job that I am after?
Is there another way of doing this I haven't considered?
Thanks in advance
I want to make it so that no matter what browser/what user you are, you are seeing the latest version of the variable.
You need to send your updates from the browser to a server, and then have that server relay your updates to all the other clients. There are many choices for how to do this, with various tradeoffs and complexity.
One method is to simply take that number and send it to the server. Then, on next page load, the server injects that new number into the page it outputs (or it serves it up via an API call, over AJAX, via the Fetch API, or server-sent events, WebSocket, etc.). If you do this though, you will need to decide how to handle concurrency. What will happen if two people load the page at the same time?
The general system you're describing is called Operational Transform, and this is a rabbit hole you probably don't want to go down right now. Just understand that there's no magic that synchronizes things across the planet perfectly and at the same time. Your system has to account for inherent delays in some way.
I've seen that cookies are an option, however I thought cookies were client side only?
Yes, cookies are client-side. They're sent to the server with every request, but that's not a useful tool for you, aside from session identification.
I've seen that sessions are another option, are sessions server side?
They can be, but you need to find a way to know what the user is between browsers. Normally, a session ID is stored in cookies.

How would I capture the timestamp of when a link is clicked in an Email?

This may be a bit of a tricky one (for me at least, but you guys may be smarter). I need to capture the timestamp of exactly when a reader clicks a link in an email. However, this link is not a hyperlink to another webpage. It is a link formatted as a GET request with querystrings that will automatically submit a form.
Here is the tricky part....The form processing is not handled by PHP or .NET or any other server side language. It is a form engine that is hosted and managed by a cloud based marketing platform that captures and displays the form submission data (So i have no access to the code behind the scenes).
Now, if this wasn't an email I'd say it is simple enough to just use Javascript. However, javascript doesn't work so well with email, if at all (I'm just assuming there are some email clients out there that support javascript).
How would you go about capturing the timestamp for when the link is clicked without using any type of scripting? Is this even possible?
The best solution i could come up with was to have the link point to an intermediate page with javascript to capture timestamp and then redirect to the form submission. Only problem with that is that it will only capture timestamp of page load and not of the actual click activity.
There is no way to do what you want "without any type of scripting". If no scripting is done, no functionality may be added or changed.
The best option is the very one you suggested: use an intermediary page that records the request time. Barring unusual circumstances (such as a downed server), the time between a link being clicked and the request reaching the server will be less than 1 second.
Do you really need a higher resolution or accuracy than ~1s? What additional gain is there from having results on the order of milliseconds or microseconds? I can't imagine a scenario in which you'd have tangible benefits from such a thing, though if you do have one I'd love to hear it.
My initial thought was to say that what you're trying to do can't be done without some scripting capability, but I suppose it truly depends on what you're trying to accomplish overall.
While there is ambiguity in what you're trying to accomplish from what you have written, I'm going to make an assumption: you're trying to record interaction with a particular email.
Depending on the desired resolution, this is very possible--in fact--something that most businesses have been doing for years.
To begin my explanation of the technique, consider this common functionality in most mail clients (web-based or otherwise):
Click here to display images below
The reason for this existing is that the images that are loaded into the message that you're reading often come from a remote server not hosted by the mail client. In the process of requesting that image, a great deal of information about yourself is given to that outside server via HTTP headers in your request including, among other things, a timestamp for the request. Thus the above button is used to prevent that from happening without your consent.
That said, its also important to note how other mail client providers, most notably gmail, are approaching this now. The aforementioned technique is so common (used by advertisers and by other, more nefarious parties for the purpose of phishing, malware, etc) that Google has decided to start caching all mail images themselves. The result is that the email looks exactly the same, but all requests for images are instead directed at Google's cached versions.
Long story short, you can get a timestamp to note interaction with an email via image request, but such metric collection in general, regardless if its done in the manner I've outlined, is something mail clients try to prevent, at least at some level.
EDIT - To relate this back to what you mention in your question and your idea of having some intermediary page, you could skip having that page and instead you would point an image request towards a server you control

Onunload, onbeforeunload - guidance requested

I have a web server that generates questions for students of a particular subject. The web server needs to keep track of how much time each student has spent on a particular set of questions.
The web pages have a "Finished" button, which, when pressed, causes statistics to be sent to server.
However, I also want the web browser to send statistics if the student navigates away from the page or closes the browser window without pressing "Finished".
For this purpose, I have planned to have "onunload" or "onbeforeunload" send an Ajax request to the server with the relevant information. But apparently different browsers do not fully support these events, and also there are restrictions on what can be done in the event handlers. And, of course, I don't want the browse to freeze if the communication with the server fails.
So, I need some advice on the best way to do this.
If I wanted to be sure to handle all the "special events" I would send tick 'requests' from the webpage to the server. Granularity depends on the tracking requirements, the load, and whether it is an intranet or internet application; can be some seconds or even a minute. So you are tracking the time spent on the page even if the browser/os/network crashes.
The best way to implement is, is to use period updates. This will pretty much guarantee you have some relevant data when the user disconnects in any way.
An implementation is pretty trivial, all tough you might have to refactor some of your logic to send out period updates instead of everything at once.
function sendStatistics()
{
// ajax and what not
}
setInterval(function(){
sendStatistics();
}, 1000);
An other way to make it work is to make your ajax call in beforeunload and make it synchronous. This will freeze the browser for duration of the call, and will also only work when navigating away or closing the browser, i don't recommend this.

How to prevent multiple ajax requests when multiple browser windows are open

I have been working on having a instant messaging system on a website(kind of like Facebook and Gmail). I have javascript poll the server for new messages.
If the user has multiple instances of the site open is there any way to prevent each one from making requests?
You can assign each "new" load of the page with a UUID, and drop requests from all UUIDs that are not the most recent one for user. You need to send the UUID back in each request. If you want to get advanced, you can have the JavaScript on the page check the response to see if the server says it's an old UUID, and that it should stop making the requests.
Register each connection with a GUID generated on the fly in the browser. Check the GUID and the username pair to see which page was owner last. On page load, declare yourself a new window and that you're taking ownership. Sort of PageJustLoadedMakeMeOwner(myGuid, username)
Then have that GUID targeted frame update the server regularly for it's ownerness of the page.
If it stops updating the server, then have rules in the server that allow the next page to contact to take ownership of for that username.
Have pages that have lost ownership self-demote to only accessing once a minute or so.
The response to check if a given page is owner of that username is really fast. Takes almost no time to do, as far as the client is aware. So the AJAX there doesn't really restrict you.
Sort of a AmIOwner(username, myGuid) check (probably do this every five seconds or so). If true, then do the thing that you want to happen. If false, then poll to see if the owner of the page is vacant. If true, then take ownership. If false, then poll again in xx amount of seconds to see if the owner is vacant.
Does that make any sort of sense?
You could do something for multiple instances in the same browser, but there's nothing you can do if the user has multiple browsers. (Granted, not that common scenario)
If you still want to give it a try, probably the easiest way would be to keep a timestamp of the last request in a cookie and make new request only upon a certain threshold. You still might run a small race until the multiple instance s settle down, but if you use fuzzy time period for the polls, the instances should settle down pretty quickly to a stable state where one of the instances makes the call and the others reuse the result from the last call.
The main advantage of that approach is that the requests can be made by any of the instances, so you don't have to worry about negotiating a "primary" instance that makes the calls and figuring a fallback algorithm if the user closes the "primary" one. The main drawback is that since it's a fuzzy timing based algorithm, it does not fully eliminate the race conditions and occasionally you'll have two instances make the requests. You'll have to fine tune the timing a bit, to minimize that case, but you can't fully prevent it.

How can I save some JavaScript state information back to my server onUnload?

I have an ExtJS grid on a web page and I'd like to save some of its state information back to the server when the users leaves the page.
Can I do this with an Ajax request onUnload?
If not, what's a better solution?
You can use an Ajax request, but be sure to make it a synchronous request rather than an asychronous one. Alternatively, simply save state whenever the user makes a change, this also protects the data if the user's browser crashes.
There's an answer above that says to use a synchronous ajax call, and that is the best case scenario. The problem is that unload doesn't work everywhere. If you look here you'll find some tricks to help you get unload events in safari... You could also use Google Gears to save content user side for situations where the user will be coming back, but the only fully safe way to keep that information is to continuously send it as long as the user is on the page or making changes.
You could also set a cookie using javascript on unload. I think the advantage ajax has over cookies is that you have the data available to you for reporting and the user (if logged in) can utilise the data across different machines.
The disadvantage of using ajax is that it might slow down the actual closing of the browser window, which could be annoying if the server is slow to respond.
It depends on how the user leaves the page.
If there is a 'logoff' button in your GUI, you can trigger an ajax request when the user clicks on this button.
Otherwise I do not think it is a good idea to make a request in the onUnload. As said earlier you would have to make a synchronous request...
An alternative to the cookie solution would be an hidden text field. This is a technique usually used by tools such as RSH that deal with history issues that come with ajax.

Categories