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.
Related
I'm trying to skip a delay event in JavaScript. Say( If I mouse wheel for 4 times continuously the first one ill get fired followed by the second, third and fourth one. In my scenario if the first event fired and when the second/third/fourth events are in delay or slow I want to speak the second and third event getting fired and must directly fire the final event (say fourth event))
Is this possible using JS/Jquery! And can anyone suggest me some sample for it if possible!
Sorry if I don’t make much sense, I am a beginner here.
It sounds like you're describing a debounce function, which will fire on the first event but merge subsequent events within a defined timeframe.
This plugin should achieve what you're looking for: http://benalman.com/projects/jquery-throttle-debounce-plugin/
This question and answer may also be helpful.
Based on the autocomplete example on this page, http://benalman.com/code/projects/jquery-throttle-debounce/examples/debounce/, the final (4th in your example) event should be fired, but any intermediate events that happen in quick succession will be skipped.
Here is a Stackblitz example, debouncing a mousewheel event to every 0.1s. You simply need to include the plugin and then do:
$(document).ready(function () {
$('body').bind('mousewheel', $.debounce(100, debounceEvent));
function debounceEvent(event) {
// Process mouse wheel event here
console.log(event);
}
});
If you do a quick scroll, only the last event should be emitted.
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?
I've got a table with dozens of rows (up to 100), and each row has 1 element with a mouseover event attached to it. On mouseover, I open a tooltip and need to make an AJAX request to fill it with some data.
My problem is fairly simple: if the user moves his mouse up and down over all the elements that have that event attached, I'm firing tons of requests at a time. I wanna throttle it one way or another, but I'm unsure how to.
I'm gonna have to check whether that same event has been executed in the last n seconds, but how do I keep a link between the firing of event 1 and firing of event 2?
You need a flag in the start of your AJAX call, if the flag is ZERO, return from the function. How you scope the varialbe is up to you.
if(AJAXOK==0) {
return;
}
AJAXOK = 1;
Set the variable in the AJAX call, so that is resets itself after a timeout:
window.setInterval(function() { AJAXOK = 1 },5000);
AJAXOK = 0;
If you're interested in trying a different approach, reactive extensions are designed for exactly this sort of thing:
http://reactive-extensions.github.com/RxJS
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;
});
});
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');
});