I'm using Ben Alman's Throttle-debounce plugin.
When I call .throttle like that:
$(window).scroll($.throttle(250, function() {console.log(1)}));
throttled function fires.
But I have to check if scroll event isn't triggered. So when I do this
$(window).scroll( function(event) {
if (!event.isTrigger) {
$.throttle(250, function() {console.log(1)});
console.log(2);
}
});
I get only "2" in result. For some reason throttled function isn't fire. (the second console printing is to show, that code goes through throttled function)
I have never used Ben's plugin, but it looks like the throttle plugin doesn't fire the function it returns a new function that can only be fired x times per second (or whatever). This works because in JS functions are first-class Objects, so a function can just return a new function.
so if you want the function to fire you need to call it,
var throttledFunc = $.throttle(250, function() {console.log(1)});
$(window).scroll( function(event) {
if (!event.isTrigger) {
throttledFunc(event);
console.log(2);
}
});
you can also re-factor your first example like
var throttledFunc = $.throttle(250, function() {console.log(1)});
$(window).scroll(throttlesFunc);
internally jquery takes your passed in function reference and when the scroll event fires it does throttlesFunc(event)
Related
What I basically want to achieve is create some kind of delayedChange plugin to be able to call some action (such as ajax call to the server) only after some delay the last input change event was fired. At the moment I've came up with this (jsfiddle). I should see alert only in 5 seconds (5000 msec) the last text change had place but it fires immediately.
(function ($) {
var timer;
$.fn.delayedChange = function (onchange, delay) {
return this.each(function () {
$(this).bind('change', function () {
if (typeof onchange == 'function') {
window.clearTimeout(timer);
timer = window.setTimeout(onchange.call(this), delay);
}
});
});
}
})(jQuery);
$(document).ready(function(){
$('input').delayedChange(function(){
alert($(this).attr('id'));
}, 5000);
});
The weirdest is that this code actually worked for some time, and then it's functionality just vanished for no reason. Obviously there is some explanation but I can't see it for now. Are there some more certain ways to implement/improve such plugin?
The functionality you've described is called "debouncing". Libraries such as underscore, lodash, and ampersand have a debounce method to make this effect convenient.'
With underscore, the code is:
$('input').each(function () {
$(this).on('change', _.debounce(...your function..., 5000));
});
No new function is needed, although you will need to include a new dependency.
I'd made a mistake with the first version. You need to generate a separate debounce function for each element, otherwise changing different elements will cause the timer to reset for all of the elements.
Out of curiosity if I am using for example.
window.onload = function() {
testFunction();
};
function testFunction() {
alert("Hello World!");
}
Does this pause the script or simply waits till the window load value is true and run the statement? I am sure its the latter but to better understand script behavior I was curious to find answer with more knowledgeable coders.
window.onload = ... is just an assignment: it stores a function in the window.onload variable. When an event happens, the JavaScript engine looks at the corresponding onsomething property and runs the function assigned to that variable. In fact, this would be valid as well:
function testFunction() {
alert("Hello World!");
}
window.onload = testFunction;
The same thing is true for functions bound with the addEventListener function.
window.addEventListener("load", function(e) {
// do something
});
window.addEventListener("load", function(e) {
// do something else
});
This simply adds functions to an underlying list of functions which will be called when the load event happens. This is required when you need to bind multiple events to the same object.
It's an event listener.
See documentation here: http://www.w3schools.com/js/js_htmldom_events.asp
and here:http://www.w3schools.com/js/js_htmldom_eventlistener.asp
You might like to try the Visual Event extension for Chrome. It shows you all event listeners that are currently attached to the page displayed.
Suppose I have this event handler:
var mousewheel = function (e) { /* blah */ };
But, I want to debounce it. So I do this, which works as expected:
var mousewheelDebounced = _.debounce(mousewheel, 500);
$(document).on("mousewheel", function (e) {
e.preventDefault();
mousewheelDebounced(e);
}
But this doesn't work as expected:
$(document).on("mousewheel", function (e) {
e.preventDefault();
_.debounce(mousewheel, 500)(e);
}
I prefer the compactness of the second form. But no debouncing occurs.
I assume no reference to the mousewheelDebounced remains, so the underlying handler is called every time. Is that the reason? How can I clean up this code, if possible?
You can see a fiddle here.
On each mousewheel event (which occurs very often) you create a new version of debounce function. This function has no history, and doesn't know that on previous event there was another one created. So it just runs. That's why you should go with the first version.
In my project I have JS module, that adds event listeners on click:
$('.next-step').on('click', function () {
// do something
});
In another module I should create new event listeners that should work AFTER previous listener. Lets say I do something like this:
$('.next-step').find('#someId').on('click', function () {
// do another things
});
The problem is that second listener always works before first. How can I change this sequence?
You can use setTimeout() function to make it be excuted later.
$('.next-step').on('click', function () {
setTimeout(
function(){alert("foo");
},100)
});
It will be executed 100 miliseconds later so you will be sure that other events already were executed.
Note: you can change 100 to 1, it will be enough.
I have a widget that I am assigning a callback function to for a specific event.
The following code works and triggers my callback just fine.
$(selector).MyFancyWidget('option', 'onComplete', this._onComplete);
My issue is after the event fires I want to remove the callback from inside the _onComplete method.
onComplete is an event that gets fired in the widget using the _trigger method and works fine.
Doing something like
$(selector).MyFancyWidget('option', 'onComplete', $.noop);
Does not detach the callback ( i assume it is just adding another listener.
For clarity here is the code inside the widget that will trigger the event.
instance._trigger('onComplete', e, {currentTarget: instance});
So my question here is how do I remove that callback?
It's not that I don't want to fire the event anymore I just don't want to listen to it anymore.
The most straightforward way of doing this would be to make the callback only do something once. So wherever you define your _oncomplete function:
var completeRan = false;
this._onComplete = function(e, args) {
if (completeRan) {
return;
}
// Rest of your code.
completeRan = true;
return this;
}