I want to display a note after the user submits a form but before he leaves the page.
Currently I'm using this (reduced example code):
$('form').submit(function(event) {
$('.note').show();
setTimeout(function() {
$('form').unbind().submit();
}, 2000);
return false;
});
This works but doesn't seem to be nice. Is there any other way, like a function $.delayPropagation(2000);?
PS: The note covers the whole screen, so the user won't be able to submit again during this time.
That is an appropriate way to delay the operation.
You may actually want to unbind the event first to stop multiple calls (you currently have a 2 second window in which they could submit again).
As a standard practice, you should only run your jQuery selectors once (use a temp var to hold the result). $ prefixes are also another standard for naming jQuery variables. This now means the code below would support multiple forms on a page separately.
$('form').submit(function(event) {
var $form = $(this);
$('.note').show();
$form.unbind()
setTimeout(function() {
$form.submit();
}, 2000);
return false;
});
You must return false immediately to avoid blocking the browser.
Notes:
An alternative would be to use Ajax for the form post, then have the delay, then goto a new page
setTimeout is the most ubiquitous way to delay code from executing.
Note: I just wanted to use the term ubiquitous in a post :)
Related
I think it very stupid question, but after hours of google it - i have no idea or solution.
Point is that i need reload page after handling "click" event on my web-site. In chrome\opera it's works without problems. But in firefox i have some bug. My JS code with comments:
$('#project_create').click(function() {
var projectname = $("#project_name").val();
var projectdescription = $("#project_description").val();
$.post("projects/add_project.php", {
project_name: projectname,
project_description: projectdescription
});
$("#create_project_form").hide("slow");
$("#project_list").show("slow");
//return false; - if it uncomment, all work, but next page reloader doesn't work.
window.location.reload(); //but if it's work, FireFox doesn't send $.post-query
});
I need to work booth methods, because after click - script put in $_SESSION['my_var'] some variable, and it variable is avaliable after reload page only. Maybe there are other ways to do it? As I understand the problem here in features with firefox and preventDefault();
Thanks!
The issue is just you reload the page before performing the ajax request.
Try to reload page in the ajax success callback handler :
$.post("projects/add_project.php", {
project_name: projectname,
project_description: projectdescription
}, function(){
window.location.reload();
});
And remove your old window.location.reload()
When you do a return, code after that line will not be reached anymore and is considered "dead code". One does not simply put code after a return.
Another is that there's and issue when using return false to prevent default default actions. It prevents delegation/bubbling. Event handlers hooked higher up in the DOM tree (especially ones hooked with on()) won't be executed. If delegation matters, don't use it.
If your goal is to prevent the default action of the link and do stuff in JS, use event.preventDefault instead. The event object is passed in as the first argument in the handler.
$('#project_create').click(function(event) {
event.preventDefault();
// rest of the code
});
In addition to what the other answers suggest, you can also execute the location.reload method asynchronously using setTimeout:
setTimeout(function() { location.reload(); }, 1);
return false;
EDIT: The entire idea of running an asynchonous AJAX request and reloading the page immediately afterwards is flawed, of course, since the AJAX request may not have been completed by the time you reload the page.
You should therefore use a callback, as suggested by the accepted answer. Alternatively, you could use a synchronous AJAX request, but that would freeze execution until the request has completed, which is generally not desirable.
In my application, there's an object that needs to be ajaxed back to the server before the user switches to another page or closes his browser.
For the moment, I'm using something like this:
$(window).on('unload', function () {
$.ajax(....);
});
Will the ajax call fire in all browsers or are there situations where this will not work and where this situation needs to be handled differently? I don't need to deal with anything in terms of a success function, I'm only concerned about the information making it to the server.
Thanks.
If you're using jQuery, you can set async to false in the ajax call. And it might work, but your results may vary by browser. Here's a jsFiddle example. http://jsfiddle.net/jtaylor/wRkZr/4/
// Note: I came across a couple articles saying we may should to use window.onbeforeunload instead of or in addition to jQuery's unload. Keep an eye on this.
// http://vidasp.net/jQuery-unload.html
// https://stackoverflow.com/questions/1802930/setting-onbeforeunload-on-body-element-in-chrome-and-ie-using-jquery
var doAjaxBeforeUnloadEnabled = true; // We hook into window.onbeforeunload and bind some jQuery events to confirmBeforeUnload. This variable is used to prevent us from showing both messages during a single event.
var doAjaxBeforeUnload = function (evt) {
if (!doAjaxBeforeUnloadEnabled) {
return;
}
doAjaxBeforeUnloadEnabled = false;
jQuery.ajax({
url: "/",
success: function (a) {
console.debug("Ajax call finished");
},
async: false /* Not recommended. This is the dangerous part. Your mileage may vary. */
});
}
$(document).ready(function () {
window.onbeforeunload = doAjaxBeforeUnload;
$(window).unload(doAjaxBeforeUnload);
});
In Google Chrome, the ajax call always completes before I navigate away from the page.
However, I would VERY MUCH NOT RECOMMEND going that route. The "a" in ajax is for "asynchronous", and if you try to force to act like a synchronous call, you're asking for trouble. That trouble usually manifests as freezing the browser -- which might happen if the ajax call took a long time.
If viable, consider prompting the user before navigating away from the page if the page has data that needs to be posted via ajax. For an example, see this question: jquery prompt to save data onbeforeunload
No, unfortunatelly your Ajax call will not get completed as the document will unload during the async call.
You cannot do many things when the user closes the window.
Instead of doing an ajax sync call (deprecated on latest browsers and can get exception), you can open a popup:
$(window).on('unload', function () {
window.open("myscript.php");
});
You can add obviously parameters to the link and you can automatically close the popup if you like.
Popup blocker must be disactivated for your domain in the browser options.
You have to use the onbeforeunload event and make a synchronous AJAX call.
$.ajax({
...
"url": "http://www.example.com",
"async": false,
...
});
I'm currently working on a simple form that stores users inputted information to a database.
The form will be displayed on iPads at a Kiosk.
If a user walks up to the form and starts to fill in the fields, but doesn't finish and walks away, I want the form fields to clear for the next person.
This is being done to prevent someone from walking up to an iPad with half of the previous users information that was never submitted.
I know I'll have to use Javascript, but I have no clue where to start.
I would say handle the keydown event of the window object and save the current time. Something like this:
var timerID = null;
var timeoutDuration = 60000; // Put the timeout duration here
window.addEventListener('keydown', function(e) {
if(timerID !== null) {
clearTimeout(timerID);
timerID = null;
}
timerID = setTimeout(function() {
// Clear all the fields here
}, timeoutDuration);
}, false);
Here's a demo.
Why not just reload the page after a period of inactivity? Safer bet. Just use setTimeout and clearTimeout JavaScript functions to achieve this when the fields get updated to reset the timers. Use setTimeout to reload the page. This will ensure that the page is reset.
See Reload and JavaScript timing.
In my opinion, the best thing to use it the javaScript timing event.
This can be done by setTimeout() and clearTimeout() functions. Then in those functions you can address the input boxes document.getElementById("nameofElement") and then clear them.
Good example that is easy to follow see :
JavaScript Timing Events
Hope this helps.
This is a really basic JavaScript question and probably duplicate, but I don't know the answer!
I have code as follows:
function userlist_change(myval, function_type) {
// relatively slow code involving Ajax call
// based on Ajax results, change some client-side stuff
}
$("#subjectlist").change(function() {
userlist_change($("#subjectlist").val(), 'change');
}).change();
$("#subjectlist").keypress(function() {
userlist_change($("#subjectlist").val(), 'keypress');
});
I have the problem that if the .change() event is called, the userlist_change function kicks off, and it's relatively slow. If the user changes the list again (e.g. by typing), my code waits for userlist_change to complete before restarting it with the new value.
This looks quite odd in the UI, as it can take a few seconds for anything to change client-side - and sometimes the results of the first call only appear after the user has already made a second call.
Is there any way I can interrupt any existing userlist_change process when the .change() or `keypress() event is fired?
[EDIT] What would be ideal is a simple 'kill any running functions with this name' command - is this possible? Or do I really have to fiddle around with timers?!
you can store last request time in a global variable, and store a request time in each ajax request, so that when you are just showing the result of first request, if the global last request time is greater than request, request time, you should show, other wise not. For example:
var lastRequestTime;
function userlist_change(myval, function_type,requestTime) {
// relatively slow code involving Ajax call
// based on Ajax results, change some client-side stuff
if(lastRequestTime <= requestTime){
//show
}
}
$("#subjectlist").change(function() {
lastRequestTime = new Date();
userlist_change($("#subjectlist").val(), 'change',lastRequestTime );
}).change();
$("#subjectlist").keypress(function() {
lastRequestTime = new Date();
userlist_change($("#subjectlist").val(), 'keypress',lastRequestTime );
});
You should use throttling of event. It is quite easily done with RX for JavaScript, but library is quite complicated. You can try filter value with timer.
Here is useful plugin for throttling: http://benalman.com/projects/jquery-throttle-debounce-plugin/
I'm using jQuery to change the HTML of a tag, and the new HTML can be a very long string.
$("#divToChange").html(newHTML);
I then want to select elements created in the new HTML, but if I put the code immediately following the above line it seems to create a race condition with a long string where the changes that html() is making may not necessarily be finished rendering. In that case, trying to select the new elements won't always work.
What I want to know is, is there an event fired or some other way of being notified when changes to html() have finished rendering ? I came across the jQuery watch plugin, which works alright as workaround but it's not ideal. Is there a better way ?
As a commenter already mentioned, JavaScript is single threaded, so you can't get race conditions.
What may trip you up however, is the fact that the UI will not update itself based on JavaScript, until a thread is finished. This means that the entire method must finish, including all code after you call html(...), before the browser will render the content.
If your code after calling html(...) relies on the layout of the page being recalculated before continuing, you can do something like this:
$("#divToChange").html(newHTML);
setTimeout(function() {
// Insert code to be executed AFTER
// the page renders the markup
// added using html(...) here
}, 1);
Using setTimeout(...) with a time of 1 in JavaScript defers execution until after the current JavaScript code in the calling function finishes and the browser has updated the UI. This may solve your problem, though it is difficult to tell unless you can provide a reproducible example of the error you're getting.
use .ready jQuery function
$("#divToChange").html(newHTML).ready(function () {
// run when page is rendered
});
It's 7 years latter and I just ran into a scenario exactly like the one #mikel described, where I couldn't avoid a "timer based solution". So, I'm just sharing the solution I developed, in case anyone out there is still having issues with this.
I hate having setTimeouts and setIntervals in my code. So, I created a small plugin that you can put where you think it's best. I used setInterval, but you can change it to setTimeout or another solution you have in mind. The idea is simply to create a promise and keep checking for the element. We resolve the promise once it is ready.
// jquery.ensure.js
$.ensure = function (selector) {
var promise = $.Deferred();
var interval = setInterval(function () {
if ($(selector)[0]) {
clearInterval(interval);
promise.resolve();
}
}, 1);
return promise;
};
// my-app.js
function runWhenMyElementExists () {
// run the code that depends on #my-element
}
$.ensure('#my-element')
.then(runWhenMyElementExists);