var workViewer = {
container: document.documentElement,
popup: document.querySelector('.avgrund-popup'),
cover: document.querySelector('.avgrund-cover'),
init: function () {
this.addClass(this.container, 'avgrund-ready');
window.avgrund = {
activate: this.activate,
deactivate: this.deactivate,
disableBlur: this.disableBlur
};
},
activateModal: function (state) {
setTimeout(function () {
this.parent.removeClass(popup, 'no-transition'); //this line
this.parent.addClass(this.container, 'avgrund-active'); //this line
}, 0);
},
removeClass: function (element, name) {
element.className = element.className.replace(name, '');
}
};
module.exports = workViewer;
I want to pass this into setTimeout function, whats the right way to do it?
This is my first post, please let me know if i can improve it in any way
There's two major ways. The first is saving a reference to this and using it instead:
var self = this;
setTimeout(function() {
self.parent.removeClass(popup, 'no-transition');
self.parent.addClass(self.container, 'avgrund-active');
}, 0);
The other is to use bind to create a new function with this bound to the given value.
setTimeout(function() {
this.parent.removeClass(popup, 'no-transition');
this.parent.addClass(this.container, 'avgrund-active');
}.bind(this), 0);
If you're running in an environment that supports them, you can also use an arrow function.
setTimeout(() => {
this.parent.removeClass(popup, 'no-transition');
this.parent.addClass(this.container, 'avgrund-active');
}, 0);
You can use Function.prototype.bind(). It creates function which is bounded to the given context:
setTimeout(function () {
this.parent.removeClass(popup, 'no-transition'); //this line
this.parent.addClass(this.container, 'avgrund-active'); //this line
}.bind(this), 0);
Related
I’m trying to stop the throttledFunction from running unless the “fly” event listener has been emitted. But I can’t change the “this.ballhit” variable from inside the eventlistener.
I don’t know how to pass variables between functions within the component.
AFRAME.registerComponent('ballflyact', {
init: function () {
var el = this.el;
this.ballhit = '';
el.addEventListener('fly', function () {
this.ballhit = true;
});
},
tick: function (t, dt) {
if (!this.ballhit) { return; }
this.throttledFunction(); // Called once a second.
},
});
When you create a function, this becomes different.
You can use self-binding function el.addEventListener('fly', () => { // ... });
Or like var self = this; el.addEventListener('fly', function () { self.ballHit = true; });
The following works. Thank you. Now the throttle function will only run for ~10,000 milliseconds after the “fly” event, not constantly in the background.
AFRAME.registerComponent('ballflyact', {
init: function () {
var el = this.el;
this.ballhit = '';
var self = this;
el.addEventListener('fly', function () {
self.ballhit = true;
// more code
setTimeout((e)=>{
self.ballhit = '';
}, 10000)
});
},
tick: function (t, dt) {
if (!this.ballhit) { return; }
this.throttledFunction(); // Called once a second.
},
});
In JavaScript, I have an element (which is an input tag).
This code :
element.addEventListener("focus", function () {
this.parentNode.parentNode.style.outline = this.parentNode.parentNode.dataset.ans_outline;
});
When the input is focused, outline is changed immediately.
My question is : how could I delay this event ?
I've tried :
element.addEventListener("focus", function () {
setTimeout(function(node) {
node.parentNode.parentNode.style.outline = node.parentNode.parentNode.dataset.ans_outline;
}(this), 1000)
});
.. But it doesn't work :(
try this:
element.addEventListener("focus", function () {
var node = this;
setTimeout(function() {
node.parentNode.parentNode.style.outline = node.parentNode.parentNode.dataset.ans_outline;
}, 1000)
});
First argument of setTimeout function is function you want to execute (do not call this function directly).
You can store reference to this in node variable and then use it inside your timed out function (see closures)
Remove the reference to the this and give it this way:
element.addEventListener("focus", function () {
$this = this;
setTimeout(function() {
$this.parentNode.parentNode.style.outline = $this.parentNode.parentNode.dataset.ans_outline;
}, 1000)
});
This question already has answers here:
How can I pass a parameter to a setTimeout() callback?
(29 answers)
Pass correct "this" context to setTimeout callback?
(6 answers)
Closed 9 years ago.
I am trying to show a div of information on a bar graph if the user hovers over the bar for a second. The answers on this site have gotten me to this point
var timer;
$(".session_hover").on({
'mouseover': function () {
timer = setTimeout(function () {
$(this).children('.session_info').css({'top':175,'right':20}).fadeIn('fast');
}, 1000);
},
'mouseout' : function () {
clearTimeout(timer);
}
});
The above code works when I replace $(this) with $(".session_hover") but then, of course it triggers all the other $(".session_hover") on the page.
How can I pass $(this) into my setTimeout function so that it only applies to the child element of the div I am hovering over?
Thanks for your help!
Try creating a closure around a variable to capture $(this), and then use it in your function:
'mouseover': function () {
var $this = $(this);
timer = setTimeout(function () {
$this.children('.session_info').css({'top':175,'right':20}).fadeIn('fast');
}, 1000);
},
Note that in modern browsers, you can also provide this as a parameter to setTimeout, like this:
'mouseover': function () {
timer = setTimeout(function (t) {
$(t).children('.session_info').css({'top':175,'right':20}).fadeIn('fast');
}, 1000, this);
},
However, if you want this to work in IE < 9, you need to use one of the polyfill techniques described in this MDN article.
Like this:
var timer;
$(".session_hover").on({
var self = this;
'mouseover': function () {
timer = setTimeout(function () {
$(self).children('.session_info').css({'top':175,'right':20}).fadeIn('fast');
}, 1000);
},
'mouseout' : function () {
clearTimeout(timer);
}
});
You need to hold a reference to this outside the setTimeout.
var timer;
$(".session_hover").on({
'mouseover': function () {
var ctx = this;
timer = setTimeout(function () {
$(ctx).children('.session_info').css({'top':175,'right':20}).fadeIn('fast');
}, 1000);
},
'mouseout' : function () {
clearTimeout(timer);
}
});
Another alternative is to use bind which is part of ECMAScript 5 (IE9+).
var timer;
$(".session_hover").on({
'mouseover': function () {
timer = setTimeout((function () {
$(this).children('.session_info').css({'top':175,'right':20}).fadeIn('fast');
}).bind(this), 1000);
},
'mouseout' : function () {
clearTimeout(timer);
}
});
Here's a demo using Bind
Can anyone please tell my why this doesn't work?
(function() {
window.Test = {};
})();
Test.Timers = {
c: null,
startTimer: function() { c = 0; setTimeout(this.doWork, 0); },
doWork: function() {
c++;
alert(c);
setTimeout(this.doWork, 0);
}
};
When I call Test.Timers.startTimer(), it only alerts once with a 1.
Thanks
A method doesn't "remember" its owner (its this); you can copy a method from one object to another, and treat it like any other function. It only has the right owner when you actually call it using dot-notation, e.g. this.doWork().
So your problem is that you're passing the function this.doWork to setTimeout, and then it gets called as a function without knowing its owner, and suddenly its this is window instead of your timer object. To fix this, you need to keep track of your this yourself. For example, you might write:
Test.Timers = (function () {
var newTimer = {
c: null,
startTimer: function() {
this.c = 0;
setTimeout(function () { newTimer.doWork(); }, 0);
},
doWork: function() {
this.c++;
alert(this.c);
setTimeout(function () { newTimer.doWork(); }, 0);
}
};
return newTimer;
})();
or:
Test.Timers = (function () {
var startTimer = function() {
newTimer.c = 0;
setTimeout(doWork, 0);
};
var doWork = function() {
newTimer.c++;
alert(newTimer.c);
setTimeout(doWork, 0);
};
var newTimer = {
c: null,
startTimer: startTimer,
doWork: doWork
};
return newTimer;
})();
(Note that I also changed c to this.c or newTimer.c where necessary, since your version refers repeatedly to window.c. Also note that in the second version, if you don't need external code to be able to access c, you can change it to a local variable, making things cleaner.)
As per your comment to ruakh's answer, I prefer the following approach, myself:
Test.Timers = (function () {
var this_ = {
c: null,
startTimer: function() { this_.c = 0; setTimeout(this_.doWork, 0); },
doWork: function() {
this_.c++;
alert(this_.c);
setTimeout(this_.doWork, 0);
}
};
return this_;
})();
That way, the meaning is clear as this_ looks like this, and all you have to do is get used to the closure pattern of making an anonymous function and calling it right away. Also note that I fixed your reference to c to refer to this_.c instead of a global variable c.
Alternatively, you can use .bind() to bind the function's this to a particular thing. This is built-in to Chrome's V8, at least, and perhaps Firefox as well:
Test.Timers = {
c: null,
startTimer: function() { this.c = 0; setTimeout(this.doWork, 0); },
doWork: function() {
this.c++;
alert(this.c);
setTimeout(this.doWork, 0);
}
};
Test.Timers.startTimer = Test.Timers.startTimer.bind(Test.Timers);
Test.Timers.doWork = Test.Timers.doWork.bind(Test.Timers);
How can I call a function like this with parameters applied to it?
searchTimer = setTimeout(doSearch, 250);
function doSearch(parameter) {
}
Use an anonymous function as a wrapper:
searchTimer = setTimeout(function () {
doSearch('parameter');
}, 250);