settimeout not working i dont know why - javascript

$('form[name=addform]').submit(function() {
if(error == true){
return false;
}else{
$('#loading').empty();
$('#loading').append("<img src = './images/ajax-loader.gif'/>");
$('#loading').show();
setTimeout(function(){
return true;
}, 4000);
}
error = false;
});
i need to load gif image before executes the return true. i do not use ajax for this please help

I'm not exactly sure what you are trying to accomplish, but that code won't work. setTimeout() does not pause the function it has been called from, nor does the return statement in the callback affect it.

JavaScript is asynchronous, not synchronous - setTimeout will not 'block' the execution of the next line of code. (See related What is the difference between synchronous and asynchronous programming (in node.js))
To submit the form after a delay (for what purpose is unclear) you will first need to stop the form submitting (by cancelling the event) then submit the form once again as when setTimeout callback is executed.
$('form').on('submit', function(event) {
// Prevent the form from submitting
event.preventDefault();
// 'this' is referring to the event target
var form = this;
// It may not be required to wrap the `form.submit` method but it's usually safer to do so
setTimeout(function() {
form.submit()
}, 4000);
});
Here is an example http://jsfiddle.net/xppNp/1/

Related

Delay Return to Wait for Asynchronous Functions (beforeunload event)

In this coding example the function logout() won't execute all it's async calls and won't wait till they are finished – instead page is unloading before, because the return of the beforeunload event triggers unloading the page.
$(window).on('beforeunload', function(event) {
event.preventDefault();
logout();
return;
});
What I want to try is that the event function returns AFTER several asynchronous calls in logout() are finished.
EDIT: My goal is NOT to show an alert with this! I only want to execute some code before the page is unloaded. The logout function could contain ajax requests and jQuery animations with some duration that needs to be finished.
I tried with callbacks, but end up with this, what isn't the desired result since it's returning to the callback, not to the event function.
$(window).on('beforeunload', function(event) {
event.preventDefault();
logout(function(x) { return; });
});
Since everything executed on the page would become invalid when the page is unloaded, you can't depend on the page itself to complete the async call.
One wordaround for chrome extension would be making use of background page. You could simply send message to background page inside beforeunload handler, catching all info you need to deal with, and execute the async call in background page. Sample code would be:
content.js
window.addEventListener('beforeunload', function() {
chrome.runtime.sendMessage({ info: "Here is the info you would like to pass to background page"});
});
background.js
chrome.runtime.onMessage.addListener(function(request) {
// The following is your async call
logout();
// Don't forget the following code
return true;
});
Don't forget to return true from the event listener in background page, since chrome.runtime.onMessage.addListener would become invalid when the event listener returns, see this answer for more details.
Try using async/await for your handler, that is:
$(window).on('beforeunload', async function(event) {
await logout();
event.preventDefault();
event.returnValue = false; // Seems require this for Chrome
});
Of course, you should have Promise returned from logout();
But I'm not sure if this is reliable.
Not really a clean solution but you can try setTimeout to force the code to wait while the logout is in progress.
var timeToLogoutInMs = 500;
setTimeout(function() {
// Nothing
}, timeToLogoutInMs);
EDIT: Why do you need to do this on the beforeunload hook? Why not set a manual option user to log out?

Combining multiple keyups into single event to reduce number of ajax requests

I have a keyup event on a search box that produces suggestions by fetching data from db. It is working fine. But the problem arises when i press keyboard buttons quickly and for every keyup event it gets me the result which produce duplicates.
I tried using
$("#search").on("keyup", function() {
setTimeout(getLocationFromDb, 1000);
});
But that still is producing same result (sending request to server for every keyup event).
I was looking for solutions but couldn't find one. Thanks for help.
EDIT
I am clearing the results beforeSend and appending the results in success.
Your approach isn't that bad - just make sure to clear all old timouts before setting a new one. You of course have to store the timeout somwhere - you could, for example, create a variable inside a closure.
This code only calls your callback when there was no new input for 1 second:
$("#search").on("keyup", (function () {
var timeout;
return function (e) {
window.clearTimeout(timeout);
timeout = window.setTimeout(getLocationFromDb, 1000);
}
})());
Fiddle: http://jsfiddle.net/uq4x9/
You can use boolean variable to detect if ajax call is finished already before send new
var isAjaxSent = false;
$("#search").on("keyup", function() {
isAjaxSent = true;
setTimeout(getLocationFromDb, 1000);
});
function getLocationFromDb( .... ) {
if (!isAjaxSent) {
//body of function
// in ajax success function set isAjaxSent to false
}
}

Invoking a modal dialog to collect some information in JQuery ajax beforeSend

I am using bootstrap and JQuery. I want to know if its possible to invoke a bootstrap modal dialog before making an ajax call in '$.ajax beforeSend'? I want to collect user comments before submitting the form. I have several buttons on my page that require this behavior. So, I want to make it more generic.
Thanks
I'd suggest the use of jQuery's Deferred object (see http://api.jquery.com/category/deferred-object/).
The following is pseudo code for your buttons' event handler:
$('#theButton').on('click', function() {
var dfd = $.Deferred();
// Code to show modal dialog here.
// Pass dfd to the dialog, and have it call dfd.resolve()
// when the user has finished, or dfd.reject() in case the
// user does not complete the form.
dfd.done(function() {
// Ajax call here
});
});
The function that gets passed to dfd.done() as an argument gets only called if and when somebody calls the resolve() method on the Deferred object.
Due to the asynchronous event model in javascript, you cannot postpone the ajax request from being sent off from within beforeSend. Once beforeSend is executed, the only chance you have to "delay" the ajax request is to outright cancel it entirely by returning false from the callback.
So while you could keep track of a status variable that knows whether the form is ready to submit (return false from beforeSend whenever the form is not ready), you're much better off doing these validation checks before ever creating the ajax request to begin with.
// why do this
$.ajax('/path', {
beforeSend: function () {
if (formIsNotReady()) {
showModal();
return false;
}
}
});
// when you can do this
if (formIsNotReady()) {
showModal();
} else {
$.ajax('/path');
}

Delaying click event

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!
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.
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");
});
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.
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).

Prevent second execution until the first ends in jquery

I have the following code...
$("#myID").click(function(){
//do some ajax requisition here
//make it appears in screen with a fadeIn(300)
});
#myID is an id of one tag
But i need that this function was not called again until the actual execution ends, i tried put many different code before e after the comments but with no success, if you can help me to prevent that second execution!
The fadeIn() don't hold the execution, the code after it was executed while the effect is occurring, can someone help me?
Thanks
You can set a flag that stores the state of whether or not the AJAX function is running:
$(function () {
//set flag to allow AJAX calls
var AJAX_ok = true;
//bind click event handler
$("#myID").click(function(){
//check if it is ok to run an AJAX request right now
if (AJAX_ok === true) {
//if we can run an AJAX request then set the AJAX_ok flag to false so another one does not start
AJAX_ok = false;
//make the AJAX call
$.getJSON('<url>', function (data) {
//now that the callback function has been called, the AJAX call is done, so we re-enable the AJAX_ok flag
AJAX_ok = true;
//make it appears in screen with a fadeIn(300)
//if DATA is valid HTML then...
$(data).css('display', 'none').appendTo('#some-container').fadeIn(300);
});
}
});
});
This will only run one AJAX call from the #myID element's click event handler at a time.
Its possible to kill the previous ajax or you can create an boolean with running, when someone click you set it to true and you have an if(!running){ //do ajax }, on the callback of the ajax you set the running to false
Use a synchronous AJAX call (The default is asynchronous). See this question for details on how to do that.
There are probably 100 better ways, but...
$("#myID").click(function() {
var is_running = $(this).data('running');
if (!is_running)
$(this).data('running', true);
else
return;
/* Do stuff */
$(this).data('running', false);
}
Use callbacks to ensure the order of execution.
$("#myID").click(function(){
$.ajax({
url: 'whatever url you are calling',
success: function(){
alert('ajax done');
$('whatever "it" is').fadeIn(300, function(){
//code place here will not execute until after fade in
alert('fadeIn done');
}
}
})
});

Categories