How to handle double-click on web pages? - javascript

Examining our web logs we find a significant number of clicks are other double-clicks, or repeat-clicks (e.g. when the system is busy and has not reacted quickly enough).
Double-Clicking a SUBMIT button may cause a form to process twice (generally we program against this, but I'd like to avoid possibility of errors that we have not programmed against), but even double clicking a link means that the server has to process the response twice (usually the server will detect a "disconnect" on the first click and abort processing for that - but we still incur the server-time for the effort, which is compounded when the server is under heavy load).
Having said that, there are times when I never get a response to a click, and its only the re-click that works.
One action we do see is a mis-click - click on a link, realise that it was not the desired link, and then click on the correct, adjacent, link - clearly we still need to allow that.
How do you handle this / what do you suggest? and what is the best way to achieve this, generically, across the whole application?
1) We could disable the link/button after click (perhaps for a set period of time, then re-enable)
2) We could hide the "body" of the page - we have done this in the past, just leaving the "banner" pane (which looks the same on all pages) which gives the appearance of the next page loading (but does not play well with the BACK button in some browsers) - this also mucks up users who mis-clicked

You could do this with a combination of delegate and data:
$(document).delegate('a, :button', 'click', function(e) {
var lastClicked = $.data(this, 'lastClicked'),
now = new Date().getTime();
if (lastClicked && (now - lastClicked < 1000)) {
e.preventDefault();
} else {
$.data(this, 'lastClicked', now);
}
});
This will prevent constant rebinding, so should have decent performance.

You can set custom attribute once the element is clicked then check for that attribute: if exists, ignore the click.
This will not change the UI of the element, just ignore repetative clicks.
Rough example using pure JavaScript (as you didn't tag your question with jQuery) is available here: http://jsfiddle.net/248g8/

If this is a big concern for you (and if the obvious answer of "make sure your server always responds really fast" isn't possible ;-) I would suggest a modified version of your (2) is the way forward.
The critical thing here is to give the user sufficient feedback that they feel that something is happening - ideally without blocking off the possibility of the user clicking again in those few cases where something genuinely has gone wrong.
Using javascript to make a small swirly "loading..." graphic may be effective here - and it's easy to set this up so that browsers that don't support javascript (or have it disabled) fall back to the standard link behaviour. Though I would only do this for forms where there is an expectation of taking a long time (or where this might scare the user) - it will make the site rather distracting to use, and in any case (a) users are used to links occasionally being slow on the internet, and (b) your server should be powerful enough to cope with the occasional extra hit :-)
You can disable the link or submit button - but this is frustrating for the user in the case where the submission fails for some reason (my bank does this, and TBH it scares me that they don't realise they should instead "program round" the double-submit issue as you described it!).
I certainly wouldn't disable the link and then re-enable it after a timeout - this would be very confusing for the user...

If you're using jQuery, then maybe you can listen for double clicks across the <BODY> tag and then prevent propagation.
$("body").live('dblClick',function()
{
return false;
});

I would say either:
Just leave it. As long as you've programmed against double-submissions on forms, who cares about a few extra processes?
Disable the link for a few seconds, as you've suggested. That was my first thought before I got to that part of your question. With jQuery (alter for your library of choice):
$('a').live('click',function()
{
var returnFalse = function () { return false; };
$(this).click(returnFalse);
window.setTimeout(function () { $(this).unbind('click',returnFalse) }, 3000);
}

Related

Ziggeo: Submitted event fired multiple times

We are using ZIGGEO to record video interviews in our new platform. I have noticed that sometimes it seems that the submitted event is fired more than once when the user submit the video. It doesn't happen all the time. Is it something that we can control?
ziggeo.ZiggeoApi.Events.on("submitted", (data: any) => {
this.addAnswer(data);
});
The addAnswer method is called multiple times, sometimes.
I saw that you send us a message to support as well Jordi, as mentioned there happy to help you with this here or there :)
For those that do not know I work at Ziggeo :)
In regards to the submitted event it would usually be called as:
ZiggeoApi.Events.on("submitted", function ( data ) {
//Your code goes here
});
I am not sure if the way you are using it currently could cause any issues, however what I presume to be happening is that there might be 2 embeddings on the page.
The reason why I say that is because v1's submitted event will fire each time some (any) Ziggeo embedding on your page raises the same.
If you want to make sure that events fire in more private manner, I would actually suggest using v2.
I consider v2 much better than v1 in a lot of different aspects, while both are great on its own (good to point out that these are 2 different systems if you will, v2 is not built on top of v1).
While v2 does not have submitted event it has a better one called verified which fires once the video is uploaded and before processing, requiring less time to tell you if the video would for some reason fail to be processed or not - you can read more about that on our forum
This would make it fire for specific video only, and could not be affected by multiple embeddings so I would suggest trying that one out.
You can see how to set it up:
The embedding
codes
Available
parameters
Events
on all of those pages you can change the version (v1 / v2) and on some even the revision to show you only relevant details for revision you are using.
PS: Might be good to see if this is specific to any browser maybe as well, causing the event to be called again for some reason.

How to handle reload & close button differently?

I want to put some logic before user leaves a page, but I want to handle reload button & close button action differently.
All I know is that there is onbeforeunload event that will be called before user unload the page, but it doesn't solve my use case.
I want to create some statistic/tracker, something like this:
$(window).beforeunload(function() {
if (user click browser's close button)
// track_user_click_close_button()
else if (user click browser's reload button)
// track_user_click_reload_button()
});
You can't know the URL user will be navigating to. This is not a jquery/js issue.
The bottomline is - you cannot do what you want.
Update
But if you try sometimes, you might find - you get what you need.
As stated in this SO answer to a similar question, there is something you can do to overcome this inability. I strongly suggest you to read the described approach.
If it's not suiting your needs, please open a new SO question with detailed explanation of what you're trying to do, and we'll try to help you.
Another update
Unfortunately, there's no way of determining this out-of-the-box. You can try the following approach:
$(window).beforeunload(function() {
// should be a synchronous AJAX-call, as async one won't work
persistLeaveOnServer();
});
$.ready(function() {
tellServerWeAreBack();
});
And on server side you should maintain the session state according to that. Once certain amount of time has passed (probably, several seconds), you consider the session ended and persist the statistics as UserClickClose. If tellServerWeAreBack request is received before this time passed, you save UserClickRefresh stat value.
beforeunload fires whenever the user leaves the page. If you want to differentiante between a refresh and a close you must be able to detect the page reload.
You could keep an information telling the page that it is unloading at xx:xx time. Log the fact to some place. When the page is loaded, check whether there is some logged evidence that the page was quit recently (depending on your definition of recently) and turn the event into a refresh event: (see here for an example)
This may not be able to differentiate between a refresh and a user closing then reopening the page quickly (under your time treshold).
Note: the linked page mentions using hidden form elements that are persisted between refresh, but says that browser support is all over the place; I'm wondering if this is still the case or not. Storing information in the window object will survive refreshes so you may want to explore this avenue

What is the best way in javascript to force a popstate on return from a different page

I am sure others have encountered this problem before, but this is doing my head in.
I have a page that generates a list of products. It's a long list so may go over several pages. I have Back and Next buttons to achieve this and they work if the user stays with the list.
The problem occurs when the user selects a product from the list and navigates away to a new page to display more details on the product. When the user has finished with this page and exits, the list of products is redisplayed at the point at which the user left it.
In chrome, the popstate is fired, and I have to adjust the number of go-backs required (due to pushStates I have already performed) on the next popstate in order to get the back button to then go to the correct previous page. In firefox, the page is being restored from the cache, and I am not being given the chance to intercept the return and make the necessary adjustments.
Is there some way to force Firefox to clear the cache and trigger the popstate when the back button or exit button is selected from the product detail page?
I've used this jQuery code before, and it works cross-platform:
$(window).bind('popstate', jQuery.proxy(function() {
// your code here
}, this));
The code inside the callback will run anytime the user presses the back button.
It's unlikely to be easy to force Firefox to clear its cache for security reasons. Here's one tip I found that might work (untested by me). But hopefully you can use this callback to do something else that's useful, like setting your navigation state correctly.
You might be able to find more useful information here.
I think you need a window.onunload handler. See https://developer.mozilla.org/en-US/docs/Using_Firefox_1.5_caching which talks about the introduction of bfcache.

check document if there is mouse moving or touching like screensaver

as the title says, i would like to know if theres any possibility in javascript (jquery) to check if there is any action in the document, and if not. something like a screensaver should pop up!
if someone is on the page and looks here, looks there and after a while he doesnt do anything, the mouse (or touch finger) stands still, i want to say the document after a minute without activity...
function noactivity() { //after 60000ms start something here }
i want that global for the whole document!
thanks ted
It can be done relatively simply in jquery using:
setTimeout();
http://jsfiddle.net/bernie1227/hNkTy/1/
I had this issue a while back while I was working on an iframe resizing issue. What I wanted was to tell the parent page whenever there is a change in height of the document.
What I found was that jQuery does not give such facility directly. The main reason for this is that there are too many activities happening to DOM which are not visible, when you are watching it (bind). You could however watch for a specific property like mouse moving on a document.
$(document).mousemove(function(e){
console.log(e.pageY);
console.log(e.pageX);
});
But then again that does not at all mean that the user is interacting with your page. That merely signifies that the user is on your page and his mouse is moving. The user might also be not moving the mouse and merely using his keyboard to interact with your page. So now you would have to watch for keyboard interaction aswell.
$(document).keyup(function(e){
console.log('active');
});
Using these you could create a countdown function which checks for a flag after a set interval of time. You could set the flag if user makes an activity. And after a set amount of time that function the 'noactivity()' function id the flag has not been set.
Another approach to watching the document activity could be you watching the DOM subtree being modified.
jQuery(document).bind('DOMSubtreeModified', function() {
console.log('active');
});
This works for Chrome/FireFox/IE8+ but not on Opera (any version). The main reason being that the operation is too heavy on your browser's resources. And I would discourage using this approach because listening for DOM mutation events may harm performance and the relevant W3C working groups are trying to find a better way to do this and deprecate DOM mutation events for this reason - it's hard or impossible to make a good and performant implementation.
I am not saying that the other options that I mentioned above are good either. They are also expensive operations if you are watching document and should be avoided. Another issue with those options is that the iframe content is not particularly the part of your document and these options will not work if user is interacting with iframe content.
So the conclusion is that W3C did not yet finalize a cheap way where user can watch changes in document subtree.

Is there a way in History.js to know when the back button was pressed

I've started to test History.js. After understanding how it works and that there is no popstate, instead there is statechange. I'm looking for a way to differ when the back button of the browser has been pressed.
The reason is that I need to know the URL before the state moved, from the one I'm going to. With the gist the project includes, only the URL we go to is looked.
I hope the solution is not to track latest URL visited in a global variable.
Thanks
I found the solutions on github to be a bit overdone for my purposes. I created a bool that is always true except right before when I used History to change the state.
var manualStateChange = true;
History.Adapter.bind(window,'statechange',function(){
if(manualStateChange == true){
// BACK BUTTON WAS PRESSED
}
manualStateChange = true;
});
Any time I change the state programmatically, set the bool to false:
manualStateChange = false;
History.pushState(null, null, currentPath);
I know this is a pretty dated question, but I came up to a solution to issues with the back/forward button when switching between a standard page and a History-state page.
Scenario:
Use HTML5 History (or history.js plugin) on a set of pages
Then other pages we need real loads, aka a standard page (don't ask why, but there are certain use cases that this may be needed)
When you go from a History-state page, and do a real load to a standard page. You cannot go BACK: it changes the url, but doesn't load the page--it only fires a statechange; which I assume is the issue of the original post. My personal opinion is that this is a browser bug (all browsers have the issue, though), because the browser should know the page you're on was reloaded outside of the History-state page.
I fixed this with something really simple:
Listening to the statechange event and tell the browser to refresh when it does fire. This way I don't care if they go back or forward out of this page. If the browser thinks the state is changing (links don't fire the statechange event), only back/forward INTO a History state page fires this event, so it solves the issue.
Code, using jQuery + History.js plugin:
$(window).on('statechange', function() {
window.location.reload();
});
If this doesn't make sense, you're probably not having this issue. However, I've noticed this on many sites that do use HTML 5 History (even pinterest.com has this issue if you reload when on an image modal and then try to go back).
Hopefully, if you do have this issue, you'll find this answer and have a huge sigh of relief :)
I finally managed all links using History.pushState, that way there is no need to differ a back button pressed. We handle all state changes the same way.
Edit: Found these two issues in History.js' Github, might help someone.
https://github.com/browserstate/history.js/issues/70
https://github.com/browserstate/history.js/issues/47
In the 'offical' version this feature is not available. Try to use this file in the main while:
https://github.com/danger89/history.js/blob/master/scripts/bundled/html5/jquery.history.js
I can't guarantee that his solution works for every browser. But it's a nice solution. If you applied his changes, you can use:
var State = History.getState();
if (State.navigation) {
// Back / forward button is pressed.
}
More information can be found on Github issue 47.
Similar answer than that of James Wagoner.
the 'statechange' event was being fired both ways, so instead I only check for a 'popstate' event, which in my case is only called when the user goes back.
window.addEventListener('popstate', function() {
window.location.reload();
});

Categories