Using "THIS" inside function - javascript

How can I use "this" in this case?
I got an error.. The page can't set display at null or undefined.
<button onclick="myFunction(this)">
<script>
function myFunction() {
this.style.display='none';
}
</script>

You can use func.call to bind a context for that function invocation (otherwise in your case it will be pointing the the global object (window) ):
myFunction.call(this);
or with myFunction(this)
You should do:
function myFunction(elm) {
elm.style.display='none';
}

An even better idea is to register the click event using addEventListener instead of with onclick inline in the HTML:
var theButton = document.getElementById("theButton");
theButton.addEventListener("click", function(e) {
var originalElement = e.srcElement || e.originalTarget;
originalElement.style.display = 'none';
});
Of course, you'll need to either give the button the same id I did -- theButton -- or otherwise retrieve it, but this is a much more flexible and modern way to handle the event.

Related

getting the element's id from on click with (this)

To initiate the onclick event, I have this
[].forEach.call(btnAddVendorDropDown, (btnAddVendorDropDown) => {
btnAddVendorDropDown.addEventListener('click', onAddVendorDropDownClick, false);
});
The function is
function onAddVendorDropDownClick(e) {
e.preventDefault();
addNewClass(modal, 'is-active');
addNewClass(modalAddVendorDropDown, 'is-active');
const test = $(this).attr('id');
console.log(test);
return test;
}
So what I'm trying to do is when a user clicks btnAddVendorDropDown, the function onAddVendorDropDownClick is called. I need to grab the id from the element. When I do console.log of the element attribute id from inside the function, I get exactly what I need. The problem I'm running into is when I try to grab it from outside the function, I keep getting undefined. I don't understand how I can grab the id once it calls this function from outside this function.
I tried this
var num = onAddVendorDropDownClick();
console.log("the function return is " + num);
Which is what shows undefined.
this is related directly to the caller's scope. This means that without "binding" a scope to your event handler, this is going to refer to your main application scope, and not the scope that jquery passes as you chain functions.
You can either wrap the event object's target:
function onClickHandler(e) {
$(e.target).attr('id');
}
Or you can use $(this) within the jquery context of a click handler:
$('#my-button').on('click', function(e) {
$(this).attr('id');
});
The last example works because it is occurring inside a JQuery closure, so it retains the scope from the previous function. Outside of a closure, this means something else.
$(this) is JQuery context, and you are inside javascript function. You can change the click button to JQuery to use it:
var test;
$("button").click(function(){
test = $(this).attr('id');
console.log(test);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<button id="btnTeste">
Teste
</button>

'this' doesn't work when assign and bind to a variable

I'm trying to create a custom module. I'm using prototype to add additional methods. The module will have an event, in which I will have to access a method from the module with 'this'. I will do that using bind.
I ran into a slight problem. I created a method, then using prototype, I assigned the method to a variable with the bind method. The problem is, 'this' isn't the one I passed through bind. Here's the sample code:
JSFiddle
function MyPlugin() {
this.hello = 'hello'
document.addEventListener('click', this.clickedBinded);
this.clickedBinded('e');
}
MyPlugin.prototype.clickedBinded = clicked.bind(this);
function clicked(e) {
console.log(this.hello, e);
}
var plugin1 = new MyPlugin();
How can I get clickedBinded have this as this? Meaning, I don't want this to be Window, I want it to be MyPlugin.
Update
The reason why I did: MyPlugin.prototype.clickedBinded = clicked.bind(this) and not: document.addEventListener('click', this.clicked.bind(this));, is because I'm going to have to remove the event at some point. And as this answer sais, if you're using bind in an event handler, and you want to remove the event, you have to assign the method with bind to a variable.
.bind() has to be called AFTER the object you want it to be bound to has already been created and when you're in the right context to have a reference to the desired object. You are calling .bind() when your code is first loaded. That will not have a meaningful value for this. Instead, change your code to this:
function MyPlugin() {
this.hello = 'hello';
// save bound function so you can use it to remove the listener later
this.fn = this.clicked.bind(this);
document.addEventListener('click', this.fn);
this.clicked('e');
}
MyPlugin.prototype.clicked = function(e) {
console.log(this.hello, e);
}
// method that will remove the event listener
MyPlugin.prototype.stopClick = function() {
document.removeEventListener('click', this.fn);
}
var plugin1 = new MyPlugin();
Notice in this fixed version that .bind(this) is called ONLY when we already have this that corresponds to our current object.
In your version, you were calling clicked.bind(this) when your code was first loaded and this would have a global value which in strict mode would be undefined and in non-strict mode in the browser would be window. The object that you will create with new MyPlugin() doesn't even exist yet when you were calling clicked.bind(this) so there's obviously no way that this could contain the appropriate value.
If you want to be able to remove the event listener later, then just store the bound listener so you can use it later.
As jfriend00 explained, you should bind the event listener inside the constructor. Each instance will have a different listener.
If you want to be able to remove the listener, store it in the instance:
var click = document.getElementById('click'),
remove = document.getElementById('remove');
function MyPlugin() {
this.hello = 'hello';
var listener = clicked.bind(this);
click.addEventListener('click', listener);
remove.addEventListener('click', function self() {
click.removeEventListener('click', listener);
remove.removeEventListener('click', self);
});
}
function clicked(event) {
console.log(this.hello);
}
var plugin1 = new MyPlugin();
<input type="button" id="click" value="Click me" />
<input type="button" id="remove" value="Remove listener" />

Javascript IE8 not passing 'this' in attachEvent

Here is a script that looks at the links that exist on a page and binds a mousedown event listener to each link. When a mousedown event is triggered it calls a function that creates an alert with the link's href. In IE9+, this works fine, but in IE8, this is undefined.
<html>
<body>
test
<script>
var c=function(){alert(this.href)};
var a=document.getElementsByTagName("a");
for(var b=0; b<a.length; b++) {
if (a[b].addEventListener) {
a[b].addEventListener("mousedown",c,false);
} else {
a[b].attachEvent("onmousedown",c);
}
}
</script>
</body>
</html>
I've tried adding this and this.href as arguments to the function, but it doesn't look like those functions accept arguments. Anyone know how I would get this to work?
Try this:
var c = function (e) {
e = e || event; // if e is not available, use global event object
var target = e.target || e.srcElement; // some browsers use target to refer to event target, and some srcElement
alert(target.href);
};
I think IE8 uses a global event object, instead of sending parameter in callback function.
Unfortunately, in the IE event model, listeners attached using attachEvent do not have their this set to the calling element so it defaults to window (i.e. the global object).
So instead of:
a[b].attachEvent("onmousedown",c);
you can ensure this is set to the element using:
a[b].attachEvent("onmousedown",(function(fn, el) {
return function() {fn.call(el, event)};
}(c, a[b]));
Look for examples of "addEvent" function, there are many around that fix this issue.

The correct way to bind this?

I'm trying to access 'this' inside a method that is called from a button press, where this refers to both the class and the button pressed:
p.myVar = 'banana';
$('.go').on('click', this._init);
p._init = function(e){
//get the button pressed
//get this.myVar
};
To do this I bind this:
$('.go').on('click', this._init.bind(this));
The above works and I can now access my var via:
this.myVar; //banana
But I can no longer access the button.
How can I access it, use e.currentTarget or is there a better way?
You should use the data argument :
$('.go').on('click', {myVar:'banana'}, this._init);
p._init = function(e){
// use e.data.myVar;
// this is the right matching clicked element
};
I presume your declaring the event listener in a closure, if so you can use a local variable and pass it that, the reference is unique to the closure and can be accessed by the function in the listener when it is called. It becomes a kind of invisible global, the reference only exists to that specific call and the listener function but is still shared.
function initButtons(){
var selfRef = this;
$('.go').on('click',selfRef._init);
}

How to call a script embedded into a HTML element

Having the following html:
<div id="plugin">
<script>
(function(){
this.do = function(e){
alert("cool!");
};
});
<script>
<div>
how do I call this.do (say from a parent element click button event handler)?
Maybe some more information will help advising on the right solution. It's a plugin, I want both markup and script to be part of the same file. I also want to be able to do something like:
$("#plugin").*controller*.do(); from outside of the plugin.
Here's a candidate solution, inspired by Scott's answer:
<div>
(function(){
var plugin = $("#plugin");
plugin.do = function(e){ alert("cool!"); };
});
</div>
then from outside:
$("#plugin").do();
any issues with it?
This looks like you can't, as the wrapper function doesn't have a name and does not self-execute. So the code never runs. If it would run, the this keyword in a global function refers to the window object and the inner function would be globally available.
(function(){
this.do = function(e){
alert("cool!");
};
})(); // <-- additional parentheses to self-execute the wrapper function
window.do === do; // true
// use
do();
// or
window.do();
// to call the inner function
But having such a wrapper function looks like you want to avoid global functions and variables (which is good for a number of well documented reasons). In that case you could define do as private method of your module and refer to it inside the wrapper function.
(function(){
var do = function(e){
alert("cool!");
};
var button = document.querySelector( 'button' ); // get the first button element
button.addEventListener( 'click', do, false );
})();
typeof do === 'undefined' // true; the function do is only available inside the wrapper function.
why are you against just doing?
<script>
function do(){
alert('cool!');
}
<script>
you could do :
<script>
window.do = function(){
...
}
</script>
then some where else:
window.do()
You can't. The outer function expression isn't called or assigned anywhere, so it will be discarded without ever evaluating the inner function expression.
If you want to bind the function somewhere, call addEventListener on the element you want to assign it to and pass it as the second argument.

Categories

Resources