14

I'm wondering whether there's a simple way to delay the click event from being processed for a specified period of time. For example we could have

$('#someElement').on('click', 'a', function(event) {
    var duration = 1000;
    someAsynchronousFunction(); // Start as soon as click occurs
    ... // Code to delay page transition from taking place for duration specified
});

So in this case the asynchronous function would be guaranteed some amount of time to run. If it hasn't completed it's work in this time I wouldn't care and would just like to continue with the page transition. I know that it's possible to accomplish something close with

event.preventDefault();
...
setTimeout(function(){
    window.location = $(this).attr('href');
}, duration);

But this only works when the link being clicked goes to a full page. I want to be able to deal with links that are used for ajax calls (which don't change the url) as well.

I noticed that the mixpanel library has a function track_links which seems to accomplish the delay on the page transition, though that function doesn't seem to work well with the support for ajax links that I mentioned.

Any help would be great! Thanks.

Edit: So I suppose my question wasn't exactly clear, so I'll try to provide some more details below.

I don't care if the async function finishes running! I only want to give it the guarantee that it has some set amount of time to execute, after which I don't care if it finishes, and would prefer to go ahead with the page transition.

i.e. I want to delay not the start of the async function, but the start of the page transition. The async function would start running as soon as the click occured.

Hopefully this is a bit more clear!

000
  • 26,951
  • 10
  • 71
  • 101
nitarshan
  • 1,465
  • 2
  • 12
  • 11
  • i don't get it, do you want to execute the function after a delay ? r what ? – Qchmqs Jul 17 '13 at 02:47
  • I should be more specific, sorry. I want the asynchronous function to start as soon as the link is clicked, but I want it to be guaranteed a certain amount of time to run (and hopefully finish what it's doing) before the page is changed. – nitarshan Jul 17 '13 at 02:50
  • It looks like you're falling into the oldest trap in JavaScript: delaying something in the hopes it will execute after an asynchronous event has completed. Don't do that: use a callback or a promise. You don't know how long the `someAsynchronousFunction();` call will take. – msanford Jul 17 '13 at 02:50
  • then you got your question answered, use callbacks, and .done() – Qchmqs Jul 17 '13 at 02:52
  • I think this might be the same question: http://stackoverflow.com/questions/12116505/wait-till-a-function-is-finished-until-running-another-function – Jamie De Palmenaer Jul 17 '13 at 02:56
  • The problem I encountered when using callbacks was that the click handler doesn't seem to wait for it to finish. Regardless, I only want to give that async function (which in my case is reliant on being able to connect to a server) a certain amount of time before I don't care and don't want to hold up the user. – nitarshan Jul 17 '13 at 03:01

4 Answers4

15

I figured out a way to solve the problem:

var secondClick = false;
var duration = 1000;

$('#someElement').on('click', 'a', function(event) {
    var that = $(this);
    
    if(!secondClick) {
        event.stopPropagation();
        setTimeout(function(){
            secondClick = true;
            that.click();
        }, duration);
        
        someAsynchronousFunction();
    } else {
        secondClick = false;
    }
});

When the user clicks the link, it internally prevents that click from actually having any effect, and gives the asynchronous function a set amount of time to do it's work before doing a second click on the link which behaves normally.

MeSo2
  • 450
  • 1
  • 7
  • 18
nitarshan
  • 1,465
  • 2
  • 12
  • 11
  • Just a note for visitors to this thread: I had difficulties with your solution not working well (note this is in Oct 2018), but found this solution that **did** work: https://stackoverflow.com/questions/36125391/vanilla-js-delay-click-event-to-add-animation . So posting that link for anyone that finds this thread.... – Rick Hellewell Oct 04 '18 at 21:57
1

setTimeout allows you to delay running code by however many ms you want

setTimeout(function(){
    console.log('Stuff be done'); //This will be delayed for one second
}, 1000);

In reality, if you're dealing with ajax you want to respond when the ajax call is complete. It may take more or less than 1000ms. $.ajax allows you do this with the .done() method. This is an example from the docs:

$.ajax({
    url: "test.html",
    context: document.body
}).done(function() {
    $(this).addClass("done");
});
Isaac Suttell
  • 469
  • 3
  • 9
  • I guess the question was edited later but this doesn't address the core of it, which is delaying the execution of a click event (rather than cancelling it and trying to mimic it later). – Álvaro González Apr 04 '18 at 11:04
-1

window.setTimeout will execute any given function after a specified delay.

You'd call it like this:

$('yourElement').click(function (event) {
    setTimeout(function () { console.log('hi'); }, 1000);
});

But I have to wonder why you need to do this. What's the problem you're trying to solve? Usually delaying stuff doesn't really solve anything.

Esteban Araya
  • 29,284
  • 24
  • 107
  • 141
-1

jQuery's ajax functionality provides exactly what you are looking for. You can define a callback function to run after your ajax request.

Something like this:

$('#someElement').click(function(event){
    event.preventDefault();
    var loc = $(this).attr('href');
    $.ajax({
        url: "test.html",
        complete: function(){
            // Handle the complete event
            loc = $(this).attr('href');
            window.location.href = loc;
        }
    });
});

You may want to use ajaxStop instead of complete, it seems like your motivation for delaying navigation is because you have a bunch of asynchronous stuff going on and you want to make sure all your ajax stuff is complete before you navigate to that page.

Regardless I would recommend looking at http://api.jquery.com/Ajax_Events/ (a very useful page of documentation).

user1937279
  • 21
  • 1
  • 3