Reputation: 127
I have an object named Gallery with several properties and methods. One of them, setCurrentPicture, removes all existing photos and videos DOM elements from gallery container before showing new photo/video. Besides my gallery stops playing video (set this to pause mode) when the user clicks on it. This is togglePlayVideo method inside the Gallery prototype. First I remove elements from DOM and then showing new content. If this is video, I add eventListener to document, use bind method.
So, in the setCurrentPicture I want to remove EventListener on video elements. Is it possible to bind this context to document inside Array.prototype.forEach method when deleting eventListener? If I saved the necessary context into new variable then I got succeed. But then I'm trying bind, my IDE is saying 'Potentially invalid usage of this'.
Code snippet:
Gallery.prototype = {
setCurrentPicture: function(currentPhoto) {
var self = this;
Array.prototype.forEach.call(container.children, function(item) {
if (item.tagName === 'VIDEO') {
document.removeEventListener('click', self.togglePlayVideo);
}
if (item.tagName === 'VIDEO' || item.tagName === 'IMG') {
container.removeChild(item);
}
});
if (pictures[currentPhoto] instanceof Video) {
var video = document.createElement('video');
....
document.addEventListener('click', self.togglePlayVideo);
}
},
},
togglePlayVideo: function(e) {
if (e.target.tagName === 'VIDEO') {
return e.target.paused ? e.target.play() : e.target.pause();
}
}
}
In case of addition document.addEventListener('click', self.togglePlayVideo);
I can use bind instead of self: document.addEventListener('click', this.togglePlayVideo.bind(this)
.
Can I use bind in removeEventListener? document.removeEventListener('click', this.togglePlayVideo.bind(this);
Upvotes: 0
Views: 148
Reputation: 127
I should add bind this to Array.prototype.forEach.call instead of implementing this to callback function.
Array.prototype.forEach.call(container.children, function(item) {
if (item.tagName === 'VIDEO') {
document.removeEventListener('click', this.togglePlayVideo);
}
if (item.tagName === 'VIDEO' || item.tagName === 'IMG') {
container.removeChild(item);
}
}.bind(this));
Thanks to all for the answers.
Upvotes: 0
Reputation: 747
The best for you is to get familiar with what is "this" and what is "bind". You can do this by reading this brilliant description
and second part
To cut a long story short - when you declare a function with "this" like this:
in defaul case "this" will be the Window object
var f = function(){return this;};
f(); //will return Window object
when an object owns a link to your function like this:
var f = function(){return this;};
var o = {func: f};
o.func(); // will return the "o" object becuase "this" becomes o object
when you use explicit binding like call/apply you'll set this to a particular value like this:
var f = function(){return this;};
var obj = {};
f.call(obj); // will return your obj
and there is so called "hard binding". used like this:
var f = function(){return this;};
var obj1 = {num:1};
var obj2 = {num:2};
var boundFunc = f.bind(obj1); //now it's hardbound to obj1
//let's try to switch this by using "call"
boundFunc.call(obj2); // will return obj1, because it's hardbound
and this can be affected when function is called with "new" keyword:
f = function(){ this.a =1; this.b =2; };
var obj = new f(); // will set brand new object as "this" and return it
//so we will get {a:1, b:2} object as a result
Upvotes: 2