ajaxStop inside a Click event in jQuery - javascript

I have the following code which displays a confirmation div when a link is clicked. The first time I run it this works, when the ajax request is finished the deleteConfirmation div slides up. But when I try it a second time (without a refresh) the confirmation div slides up every time it's slid down, even when this click isn't triggered.
$("#deleteConfirm").click(function() {
if(debug)
console.log("deleting "+$("#deleteConfirmationCampaign").html());
$("#mappingsRemove").html("Deleting Campaign and Mappings...");
// remove each mapping underneath the campaign
deleteCampaign(apiUrl, "mappings", account+"/"+campaignToDelete[1], "confirmDelete");
$(document).ajaxStop(function() {
$("#mappingsRemove").html("Finished");
// slide up the delete confirmation dialog
$("#deleteConfirmation").slideUp();
});
});
I have several requests that occur in my deleteCampaign function, am I using this incorrectly?
I think whats happening is the first time this triggers it sets a global listener for ajaxStop. And of course this triggers like all of the time, so it always tries to slideUp the confirmation div. Perhaps I need to stop the document listener to ajaxStop after it's slid up for the first time?
Any advice would help thank you!

You're right about what happens. But i'm not sure that ajaxStop is the best event to listen to. It fires when all requests have finished, right?
I think you would want react only on the requests that are related to your deleteCampain function.
You could use deferreds to execute a function when all the significant request have returned.
var ajax1 = $.ajax("/deleteCampain.php"),
ajax2 = $.ajax("/deleteCampain2.php");
$.when(ajax1, ajax2).then(function(){
$("#mappingsRemove").html("Finished");
$("#deleteConfirmation").slideUp();
});
See:
http://api.jquery.com/category/deferred-object/
http://api.jquery.com/jQuery.when

You might set a global boolean so it only runs one time:
$(document).ajaxStop(function() {
if (!window.firstStop) {
$("#mappingsRemove").html("Finished");
// slide up the delete confirmation dialog
$("#deleteConfirmation").slideUp();
window.firstStop = true;
}
});

I unbinded the document and the ajaxStop function after the initial round of requests are finished,
Please let me know if this is going to cause any issues:
// listen for the ajax requests to finish
$(document).ajaxStop(function() {
// set the mappings remove to say finished
$("#mappingsRemove").html("Finished");
// slide up the delete confirmation dialog
$("#deleteConfirmation").slideUp();
// unbind the listener
$(document).unbind('ajaxStop');
});

Related

Is it good idea to use jquery function that run each 500ms?

I created some kind of lazy load for images. It works like this:
Every 500ms it check photoes which one you see on device and if you see it begin to load real image and this function will never run for images that loaded but if image cant load it will try again when you see this image again.
Is there any problem to use that kind of function every 500ms?
It sounds like you're using this in response to the images coming into view? Rather than polling every 500ms all the images on the page to see if they're in view, perhaps it would be better to trigger the check only when the page has scrolled (or whatever causes images to scroll. You could still limit this to be no more frequent than once every 500ms, but it has the benefit of:
Not having a 500ms interval loop running all the time
Not checking the images in view unnecessarily
I'll assume the images come in and out of view as the user scrolls, so what you'd want to do in that instance is as follows:
Bind an event to $(window).scroll
Have it fire an event after a fixed period with setTimeout (500ms in your case).
Cancel that timer if the user scrolls again and start it (to prevent it firing multiple times.
Listen for the event firing and perform your image check there.
Here's an example of how the code might look:
var scrollIntervalTimeout;
$(window).on('scroll', function() {
// Cancel the timeout and start it again
clearTimeout(scrollIntervalTimeout);
scrollIntervalTimeout = setTimeout(function() {
$(window).trigger('scrollDidEnd');
}, 500); // 500ms delay before firing the event
});
// Listen for the scrollDidEnd event
$(window).on('scrollDidEnd', function() {
// Perform your image check here
});

Queue up a function after click events

I have a problem with queuing up events in jQuery. I have an elevator project that allows the user to click on buttons, and then lights go on and then numbers change. That works fine, except when they punch a number again before it reaches the floor picked the first time. I want it to get to the floor first picked before it goes to the second clicked floor (or third, or fourth, etc.). I've done some stuff with .promise, when done, etc. and none of it seems to work.
I am using .click which appears to be the issue, because it fires the function regardless of where it is currently. Trouble is that I can't seem to find any alternative and it needs to finish current operation first before moving on to any other floors.
I hope I explained this well. If not please let me know. Perhaps there is another way entirely of doing it. Still learning this front end/jQuery stuff.
$( ".button" ).click(function(event) {
// doing stuff here....
$( runMainscript() ).promise().done(function() {
runMainscript(buttonclicked, floorQ);
});
});
function runMainscript(buttonclicked,floorQ) {
//doing stuff here
}
BTW, here is a timer for 2 seconds on each floor.
JSfiddle: http://jsfiddle.net/ak25Lxab/1/
See how if you click on two buttons quickly, it jumps around?
The deferred object works slightly differently. You should explicitly declare a deferred variable like this:
var dfd = new $.Deferred();
And when you want to fire done callback, you should call:
dfd.resolve();
So your queueing part of the script now looks like this:
$.when(dfd.promise()).done(function() {
dfd = new $.Deferred();
var onfloor = $("#onfloor").text();
runMainscript(buttonclicked, floorQ, onfloor);
});
And inside runMainscript you resolve this dfd deferred when elevator arrived to the floor.
See demo. Now, all floors are in the queue using deferred object.
I'm not an expert in deferreds, so maybe you can optimise this script further.
I don't really understand your problem and your jsfiddle is not working for me but as far as I can see you want to stop listen for the click event when the elevator is moving.
To do this you can stop listening for the click event and then restore the listener.
http://api.jquery.com/off/
So ideally, listen for the click event, as soon as it's fired stop listening for the click event, do your operations and then restore the listener on the click event for the .button
Or you can try to do something like this, put a state and do nothing if the state is not cleared:
jQuery - How can I temporarily disable the onclick event listener after the event has been fired?

If an event fires a random amount of times, how do I capture the last one in Javascript/Jquery?

I have a function, that adjusts element width/height on a page. This function is triggered by a custom dimensionchange event.
I'm
$(window).trigger("dimensionchange")
whenever I'm loading content via AJAX or changing a page (I'm using jquery mobile).
My problem is on some pages, a bunch of Ajax requests get triggered (like a search page, which ajax loads criteria and intial results), so I'm ending up with several "dimensionchange" events, which all trigger my layout update function. This slows down the page considerably and is not necessary, because I only need to capture the last dimensionchange and then update the layout.
Question:
Is there a way to capture the last occurence of an event when the event fires a random amount of times? The only thing I could think of is to set a timeout on every event occurence and if there is no further event in ... 500ms... trigger the page update. But this seems pretty awkward, so I'm curious to know if there is a better way?
Thanks for help!
You want to use jQuery's Global Ajax Event Handlers ajaxStart() and ajaxStop() methods.
There is another recent post about Using AjaxStop and AjaxStart. The main thing you need to know is that you can be notified when the first ajax query begins, and when the last one ends. You could set a flag like this:
$(document).ready(function() {
var ajaxBusy = false;
$(document).ajaxStart( function() {
ajaxBusy = true;
}).ajaxStop( function() {
ajaxBusy = false;
});
});

Prevent Javascript function from firing multiple times

jsFiddle
I use a customized drop-down menu which runs on jQuery events and animations.
The problem occurs when I activate the drop-down via mouseenter several times, which results in the menu sliding down then sliding up several times. I tried to fix it by adding .stop(true), which was successful, but it resulted in other problems like this.
I followed that advice(jsFiddle Here), but it causes more unattractive problems.
I need is a way to stop a function from firing redundantly, but still be able to stop a "slide down" immediately and then "slide up" if the user triggers .mouseleave.
I tangled with custom queues for a good 5 hours, with no success :(
Any ideas, advice, and criticism is welcome.
Basically it boils down to delaying the execution of the event handler.
var mouseoverTimer = null;
$('.elem').mouseover(function(){
clearTimeout(mouseoverTimer); //ignore previous trigger
mouseoverTimer = setTimeout(function(){ //wait to execute handler again
//execute actual handler here
}, 10);
});
If the same handler was called within the specified interval the pending execution is cancelled and queued again to execute 10ms later hoping that there's no subsequent trigger within that interval.

what can i put in beforeUnload?

I would like to have an animation effect which starts when people leave a page.
I use this currently:
window.onbeforeunload = function (){
alert("test");
console.log("test");
sliderIntervalId = setInterval('SlideDown()',1);
}
While the "test" is indeed logged to the console, the neither the function slideDown nor the test alert is produced...
Is this normal behavior? can we use the beforeunload function only for backend purposes?
P.S. I'm testing on chrome, that's why I had to use onbeforeUnload i.s.o onUnLoad which seems not to be supported by Chrome?
onbeforeunload can delay the page unload in only one case: When a return statement with a defined value is returned. In this case, the user gets a confirmation dialog, which offers the user an option to not leave the page.
Your desired result cannot be forced in any way. Your animation will run until the browser starts loading the next page:
[User] Navigates away to http://other.website/
[Your page] Fires `beforeunload` event
[Your page] `unload` event fires
[Browser] Received response from http://other.website/
[Browser] Leaves your page
[Browser] Starts showing content from http://other.website/
Assuming jQuery for the sake of brevity:
$('nav a').click(function (e) {
//ignore any "modified" click that usually doesn't open in the current window
if (e.which > 1 || e.shiftKey || e.altKey || e.metaKey || e.isDefaultPrevented()) {
return;
}
//where you going here?
var place = this.href;
//you're not going anywhere, buddy
e.preventDefault();
//watch me dance, first
$('.animate-me').fadeOut(1000, function afterAnimation () {
//you're free to go!
document.location = place;
});
});
Basically, you don't use onbeforeunload. One advantage is that you can keep the user as long as you want, one disadvantage is that the user won't see an animation when using a link outside nav (but you can just change the selector)
Obviously keep the animation fast, like suddenlyoslo.com do.
Jorrebor,
If your trying to have this animation fire when they leave your site or close the browser it will not work as intended. However, you can create this animation while the user travels within your site by removing the 'href' property of your links and creating animations that have a callback function that set the window.location property. Something like:
document.getElementById('home').onclick(function(){
yourAnimationFunction(function(){
window.location="example.com";
});
});
alot of work and wont be seo friendly however
I am working with onbeforeunload and What I was able to figure out is:
onbeforeunload handler is blocking the browser from destroying the current page
if you don't return anything, the popup does not appear.
So your code will be working as long as the event handler runs.
This means that timer functions are not usable. They just add to the execution queue, so anything they would do is being queued after the end of currently running handler, which is after the last point in time you were guaranteed your code is still running.
So there is only one way to stop the browser from unloading before the animation finishes:
put a blocking loop that wastes some time in the beforeunload handler
start CSS3 animation by setting an appropriate class on the element before the loop
make the loop end when the animation finishes (make the loop check the actual height of an element or something)
Oh, and yes, this is a nastiest hack of all, but I was able to find a way to stop the browser from unloading the page, right?
I would appreciate comments with ideas on what to put in the loop.
I am taking some options into account:
wasting CPU on come math on large numbers
accessing localstorage (synchronous call, IO operration)
accessing DOM (this solution already has to)
Any ideas?

Categories