javascript debounce: how to get e.target? - javascript

I'm using the implementation of debounce from https://davidwalsh.name/javascript-debounce-function.
The question now is: How do I get the event (e.target) from the eventlistener and use it inside the debounced function?
This is what I've come up with:
document.querySelector('textarea')
.addEventListener('input', (e) => {
debounce(
() => { console.log('debounce at '+e.target.value); },
1000,
false
)(e); // add (e) so that the function debounce returns gets called inside the anonymous function
});
The problem is that it triggers immediately (and the debounce effect gets effectively killed).

you need to wrap the input event handler, like so:
function handler(e) {
console.log('debounce at '+e.target.value);
}
const debouncedHandler = debounce(handler, 1000)
document.querySelector('textarea').addEventListener('input',debouncedHandler, false)
now when the event fires it will call the same handler and not a new one
demo

Related

How do you pass event to a setTimeout

I currently have:
var content = document.querySelectorAll(".content");
var myButtons = document.querySelectorAll(".more-button");
function enableContent(evt){
// remove class d-none so it can appear
content[evt.currentTarget.param].className = content[evt.currentTarget.param].className.replace(/\bd-none\b/g, "");
}
for(var i=0; i<myButtons.length; i++){
myButtons[i].addEventListener("click", enableContent);
myButtons[i].param = i;
}
Each myButton has it's own content. I'm trying to make content appear slowly when myButton is clicked like so:
for(var i=0; i<myButtons.length; i++){
myButtons[i].addEventListener("click", function(){setTimeout(enableContent, 2000, evt)}));
myButtons[i].param = i;
}
But it doesn't work, there is a problem with the parameter evt. How do I pass in evt to setTimeout?
I would suggest making solution easier by setting the setTimeout inside the enableConent directly
function enableContent(evt){
// remove class d-none so it can appear
setTimeout( () => {
content[evt.currentTarget.param].className =
content[evt.currentTarget.param].className.replace(/\bd-none\b/g, "");
}, 2000);
}
But if you need to learn why the event is not being passed to the enableContent event handler we need to know how setTimeout and function binding works.
setTimeout take a callback (fancy word for passing a function to another function) and a delay time(that guarantees at least x time before calling the callback function.
so using setTimeout should be used like
setTimeout( enableContent, 2000 );
yet this code won't pass the event so we need to bind the function enableContent with the event object so when the event handler is called the function know and access the event object properly
myButtons[i].addEventListener("click", function(event){
setTimeout( enableContent.bind(event), 2000);
});
binding in js has many types, implicit, explicit, hard, & new binding. using bind function bind the enalbeConent with the event and return a new function that is hard bound with the event object.
You need to pass the event (evt) to the function itself, and I think maybe you are moving the wrong way using the setTimeout, maybe you don't need to use a setTimeout? You can use css animation or transition with *-delay properties?
But if you are using setTimeout, you need to clear timeout after every click using the clearTimeout method:
myButtons[i].addEventListener("click", function(evt) {
if(evt.currentTarget.timer) {
clearTimeout(e.currentTarget.timer);
}
evt.currentTarget.timer = setTimeout(enableContent, 2000);
}));
Example: https://jsfiddle.net/6kcq2ma8/
Easy peasy!
window.addEventListener("load", (event)=> {
let setTimeoutHandler = (event) =>{
console.log(event);
}
setTimeout(()=>{
setTimeoutHandler(event);
}, 1000);
});

How to pass arguments to addEventListener listener function with typescript?

The situation is somewhat like:
const searchKeyPressHandler = (appDispatch: any, e: any) => {
if (e.keyCode === 27) {
appDispatch({ type: "closeSearch" })
}
}
document.addEventListener("keyup", searchKeyPressHandler); // <-- error on searchKeyPressHandler
return () => document.removeEventListener("keyup", searchKeyPressHandler); // <-- error on searchKeyPressHandler
searchKeyPressHandler return error using typescript and I don't know how I can avoid it.
document.addEventListener("keyup", function (e) { searchKeyPressHandler(appDispatch, e) });
could be a solution for addEventListener
but it is not useful for removeEventListener because the event will be never removed with
return () => document.removeEventListener("keyup", function (e) { searchKeyPressHandler(appDispatch, e) });.
Just wrap the actual event handler in an anonymous function and that function can then call your function with its arguments. But don't forget that event handlers are automatically passed a reference to the event that triggered them, so capture that in the outer handler and pass it along with your other arguments:
document.addEventListener("keyup", function(event){ searchKeyPressHandler(event, x,y,z); });
Or, if you need to utilize the function that you are setting up as the "wrapper" more than once (in the case of having to remove the listener later), you'd just declare the function with a name and pass that name into .addEventListner() as follows:
function handler(event){
searchKeyPressHandler(event, x,y,z);
}
document.addEventListener("keyup", handler);
// And later...
document.removeEventListener("keyup", handler);

addEventListeners and React not working as planned

I try to make a timeline that is dynamicaly loaded when scrolling.
Due to this I need the scroll event, combined with React.
window.addEventListener("scroll", console.log('scroll'), true);
This should console log a scroll every time I scroll, but it just log it once, then nothing
EDIT:
If I use it in my real application now, with this code :
callbackFunc = () => {
for (var i = 0; i < items.length; i++) {
if (this.isElementInViewport(items[i])) {
items[i].classList.add("in-view");
}
}
}
componentDidMount() {
window.addEventListener("load", function (event) { this.callbackFunc(); }, true);
window.addEventListener("resize", function (event) { this.callbackFunc(); }, true);
window.addEventListener("scroll", function (event) { this.callbackFunc(); }, true)
}
It says callbackFunc is not a function
This isn't working because the event listener expects a function as it's second argument (or an object implementing the EventListner interface) which it will call when the "scroll" occurs. console.log is a function, but console.log("scroll") isn't a function, its a called function. And so the value you are technically putting as the second argument is undefined (as console.log("scroll") returns undefined).
const a = console.log("scroll");
console.log(a); // undefined (the value of your second arugment)
So, you need to wrap the console.log() in a function, so the function is called, which will then call your console.log() method. You can achieve this by using an ES6 arrow function:
window.addEventListener("scroll", _ => console.log('scroll'), true);
window.addEventListener("scroll", _ => console.log('scroll'), true);
body {
height: 200vh;
}
As per your edit, the arrow function should solve your issue. Currently, the window is calling your event listener function, so this is referring to the window, not the context of your app. Using an arrow function should fix this (as an arrow function doesn't have it's own this).
Try this:
window.addEventListener("scroll", function(event) { console.log('scroll'); }, true);
Try adding it in reactjs
componentDidMount() lifecycle function

Don't have to pass in argument in addEventListener?

Why don't I have to pass in an argument when adding playSound(e) to addEventListener? How does the event automatically get passed in?
function playSound(e) {
const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);
const key = document.querySelector(`.key[data-key="${e.keyCode}"]`);
if (!audio) return; //stop the function from running
audio.currentTime = 0; // rewinds to the start
audio.play();
key.classList.add("playing");
}
window.addEventListener('keydown', playSound);
The code works as is
Think about it this way:
function addEventListener(event, handler) {
const eventObject = new Event();
switch(event) {
case "keydown":
handler(eventObject);
}
}
This is a simplified version obviously, but the function you pass in is called with an argument by addEventListener
First you defined the function. In usual scenarios we will call that function some where. But in this case you want to call it when a keydown event is triggered. For that you have passed that function to keydown event as a callback. Something like below is happening behind the scenes.
function keydown(callback) {
var e = getEvent(); // here it will get you the event object.
callback(e); // here your function playSound is called.
}

JavaScript Self Invoking Function on addEventListener

I'm not being able to make a function of an Event Listener self invoke and the listener to work.
The following code executes the function, but the Event Listener don't work:
window.addEventListener("resize", (function () {
document.getElementById("divMenu").innerHTML = document.getElementById("divTop").offsetWidth
})())
The function will set a needed (dynamic since the beginning) CSS style essential to the website formatting. The "resize" function MUST be executed at load.
Is it possible to make this, or should i create a separate Self Invoking Function and call it on the Event Listener?
When you immediately invoke the function, it's return value is put in it's place (window.addEventListener('resize', undefined)). Instead, define your function outside of the event listener then add it and call it.
function onResize() {
document.getElementById('divMenu').innerHTML = document.getElementById("divTop").offsetWidth;
}
window.addEventListener('resize', onResize);
onResize();
Technically, you could make this work using a self-invoking function but it's a bit screwy and I wouldn't suggest it.
window.addEventListener('resize', (function onResize() {
document.getElementById('divMenu').innerHTML = document.getElementById("divTop").offsetWidth;
// Works because it returns a function
return onResize;
})());
Your IIF returns undefined, but eventlistener must be a function, or link to function. Add return to your IIF or pass function:
Anonymous function:
window.addEventListener("resize", function () {
document.getElementById("divMenu").innerHTML = document.getElementById("divTop").offsetWidth
}))
IIF, that returns a function
window.addEventListener("resize", (function () {
return function(){
document.getElementById("divMenu").innerHTML = document.getElementById("divTop").offsetWidth
}
})())
Edited (invoke assignment on startup):
window.addEventListener("resize", (function () {
function set_innerHtml(){
document.getElementById("divMenu").innerHTML = document.getElementById("divTop").offsetWidth
}
set_innerHtml();
return set_innerHtml;
})())

Categories

Resources