When dynamically creating an element of type select, there are two problems when setting the onclick method:
It is impossible to simply set the onclick with element.onclick="updateInput(this.articleIndex)";
This results in a final HTML tag where no onclick is shown at all.
When set by e.setAttribute("onclick","updateInput(this.articleIndex)");, it does appear in the final HTML. And the updateInput method does get called.
However the functionality seems to be broken, as the argument always evaluates to undefined
Here a simple example of my problems:
var selectElem = document.createElement("select");
selElem.id="articleSelector_"+this.articleIndex;
console.log("the index of the article is " + this.articleIndex);
selElem.setAttribute("onclick","updateInput(this.articleIndex);");
//selElem.onclick="updateInput(this.articleIndex)"; //this does not work
The log shows the correct number. Inside the updateInput method, the argument is of value undefined instead of the number previously shown in the log.
Try attaching handlers with pure Javascript, and not with HTML, without onclick = "... (which is as bad as eval).
The this in your script refers to the calling context of the function - what is it?
You might want:
element.addEventListener('click', () => {
updateInput(this.articleIndex);
});
(arrow functions retain the this of their surrounding scope)
it is impossible to simply set the onclick with element.onclick="updateInput(this.articleIndex)";
What that code does is it assigns the string "updateInput(this.articleIndex)" to the onclick which makes no sense and certainly not what you want.
Even if you remove the quotes:
element.onclick = updateInput(this.articleIndex);
It is still incorrect because it assigns the result of the updateInput() function to the onclick which is again not what you want.
You need to assign a function name to the onclick like this:
element.onclick = updateInput;
However, this doesn't allow you to pass a parameter as you wish. To do so, you need to use an anonymous function:
element.onclick = function() {
updateInput(this.articleIndex)
};
When set by e.setAttribute("onclick","updateInput(this.articleIndex)");, it does appear in the final HTML. And the updateInput method does get called.
This works because it sets the attribute onclick and it is a string type, so everything is correct. It is equivalent to using the anonymous function above. The only difference is this, which in this case refers to the element itself, while in the above code it depends on the context that the code appears in. That's why in this case the argument always evaluates to undefined because the select element doesn't have an articleIndex property.
The problem is the value of the context this when that element is clicked, the context this is not available anymore at that moment.
You have two ways to solve this problem:
You can use the function addEventListener to bind the event click, and bind the function/handler with the desired context this:
The function bind binds a specific context to a function.
selElem.addEventListener('click', updateInput.bind(this));
function updateInput() {
console.log(this.articleIndex);
}
As you need a specific value, you can use data attributes. That way, you don't need to worry about the context this.
selElem.dataset.articleIndex = this.articleIndex;
selElem.addEventListener('click', function() {
updateInput(this.dataset.articleIndex); // Here you can get that value.
});
Related
This is my function and it should change the onClick attribute of the HTML input, but if I use
document.getElementById('buttonLED'+id).onclick = "writeLED(1,1)";
it does not work at all, but if I use
document.getElementById('buttonLED'+id).onclick = writeLED(1,1);
the function executes by itself!
Any ideas what code do I have to use to change the onCLick attribute WITHOUT executing the function, before the button is clicked?
Here is the full function, if it matters:
function showLED(id){
if(color == 0){
document.getElementById('buttonLED'+id).onclick = "writeLED(1,1)";
document.getElementById('buttonLED'+id).value="light is on";
//document.getElementById('buttonLED'+id).disabled = false;
}else{
document.getElementById('buttonLED'+id).onclick = "writeLED(1,0)";
document.getElementById('buttonLED'+id).value="light is off";
//document.getElementById('buttonLED'+id).disabled = false;
}
}
Well, just do this and your problem is solved :
document.getElementById('buttonLED'+id).setAttribute('onclick','writeLED(1,1)')
Have a nice day XD
You want to do this - set a function that will be executed to respond to the onclick event:
document.getElementById('buttonLED'+id).onclick = function(){ writeLED(1,1); } ;
The things you are doing don't work because:
The onclick event handler expects to have a function, here you are assigning a string
document.getElementById('buttonLED'+id).onclick = "writeLED(1,1)";
In this, you are assigning as the onclick event handler the result of executing the writeLED(1,1) function:
document.getElementById('buttonLED'+id).onclick = writeLED(1,1);
The line onclick = writeLED(1,1) means that you want to immediately execute the function writeLED(arg1, arg2) with arguments 1, 1 and assign the return value; you need to instead create a function that will execute with those arguments and assign that. The topmost answer gave one example - another is to use the bind() function like so:
var writeLEDWithSpecifiedArguments = writeLED.bind(this, 1,1);
document.getElementById('buttonLED'+id).onclick = writeLEDWithSpecifiedArguments;
Using Jquery instead of Javascript,
use 'attr' property instead of 'setAttribute'
like
$('buttonLED'+id).attr('onclick','writeLED(1,1)')
You are not actually changing the function.
onClick is assigned to a function (Which is a reference to something, a function pointer in this case). The values passed to it don't matter and cannot be utilised in any manner.
Another problem is your variable color seems out of nowhere.
Ideally, inside the function you should put this logic and let it figure out what to write. (on/off etc etc)
Another solution is to set the 'onclick' attribute to a function that returns your writeLED function.
document.getElementById('buttonLED'+id).onclick = function(){ return writeLED(1,1)};
This can also be useful for other cases when you create an element in JavaScript while it has not yet been drawn in the browser.
First we'll select the required button using query selector and for all the selected buttons we'll set the onclick attribute with a function that needs to be called by clicking on the buttons.
You can write the code for required work you want to do by clicking the button in the function defined.
Well "One of the" generalized solution to your to your problem can be achieved by the following code:
var a=document.querySelectorAll('button');
for(b=0;b<a.length;b++)
{
a[b].setAttribute("onclick","check("+b+")");
}
function check(e)
{
var sa=a[e].innerHTML;
console.log('working onclick',sa);
}
Here's a function where it suppose to work when I click a "button
but surprisingly it immediately invoked without calling!
const show_card = (shopping_card_checkout) => {
console.log("ali el-deeb");
};
document.querySelector('.fa-shopping-cart').addEventListener('click', show_card()) ;
If I tried to redo the code after the event listener it says reference error as I called the function before declaration.
Help a beginner.
Saw your post request in JS FB group and thought I'd answer here.
First you need to use document.ready or make sure that all js is loaded as last cause else the element might not yet exist. This is not th cause of your problem btw. The problem I explain as last but some advice. You use a class and querySelector, querySelector will fetch the first element in the document and if you want all elements returned you need querySelectorAll and this is not unique or would you like to bind the same action and functionality to many elements? So better would be to use the unique id of an element and use something like:
const myElement = document.getElementById("idName");
myElement.addEventListener("click", myFynction);
const myFunction = () => console.log("Clicked");
The real cause of your issue
You bind the function to the click event and bind it with () behind it and that triggers the execution cause now you don't bind the function but the result of the bound function, you can't pass parameters like that to a bound event. You will need to fetch them inside the function cause only event and a callback can be triggered.
So your working code is:
const show_card = (shopping_card_checkout) => console.log("ali el-deeb");
document.querySelector('.fa-shopping-cart').addEventListener('click', show_card);
And if only one return or one statement inside an arrow function there is no need for the curly brackets and no need to use return since it will automatically return the result of the oneliner.
I have read in a book that we have not to use parentheses when assigning a function to onclick property of an element.
<input type="button" value="Click" onClick="sayHello();" id="button1">
var b1=document.getElementById("button1");
b1.onclick=sayHello;
Why do we use parentheses inside onClick attribute of above element?
Because of how inline events (i.e. specified as HTML attributes) work.
They're generally a bad idea for a multitude of reasons (see many related posts) but the answer to your question is this.
Events specified as HTML attributes are done so as strings. Essentially, when the element is clicked, the string specified as the attribute value is evaluated (this should give you a clue as to one of the reasons they're a bad idea). For this reason, you can think of the event causing the following JS to run:
sayHello(); //<-- invoke callback
If it caused instead the following to run, nothing would happen:
sayHello; //returns reference to callback, to nowhere
If you wrote var b1.onclick=sayHello(); that would invoke the sayHello function immediately rather than waiting for the click event. You would want to use this technique if your sayHello function returns some value that you want to assign to the variable, though that would rarely be applicable when assigning the onclick property (it probably wouldn't make sense to be using the var keyword as you do in the example).
Technically, you could get the desired results from b1.onclick=sayHello(); if your code looked something like this:
<button id="b1">invoke sayHello</button>
<script>
var b1 = document.getElementById("b1");
function sayHello() {
return () => { console.log("hello"); };
}
b1.onclick=sayHello();
</script>
That would run the console.log whenever the b1 button is clicked.
In the case of HTML attributes, they are strings. You can think of assigning onClick in an HTML attribute as being roughly equivalent to this JavaScript:
b1.onclick = eval("sayHello()");
I need to set onclick property to the newly created element (input tag). It should be function with arguments. I use this: addButton.onclick = addToBasket(aHref[i].innerHTML, aHref[i].href);
But the problem is that this function calls automatically when window is loaded, but I need simply to set property. By the way if I use function without arguments like this: addButton.onclick = addToBasket; it works (isn't called automatically).
Use instead:
addButton.onclick = function(){
addToBasket(aHref[i].innerHTML, aHref[i].href);
}
onclick expects a function-definition. Another possibility is:
addButton.onclick = addToBasket;
But in this last one you will need to get the args from the function's inside, or with global variables.
It is because when you use () you are invoking the function-definition which will return some value or undefined.
You probably want this:
addButton.onclick = function(){ addToBasket(aHref[i].innerHTML, aHref[i].href)};
The difference is that the addToBasket call here is done on click, not before.
I am trying to change the value of the onblur attribute of a text input after the page has finished loading.
When I do the following, it simply fires the function:
ip.onblur = stopCalcUpInt(this,10);
When I do the following, I have success:
ip.onblur = function onblur(event){stopCalcUpInt(this,10);}
Unfortunately, the whole point of this is to be able to dynamically set the second parameter for stopCalcUpInt(). If I hard code a value for it... it works fine... but any attempts to pass varibles to this fails... instead of putting the value of the variable as the second param it just puts the plain text of the variable name itself. Here is ideally what I am TRYING to do:
ip.onblur = function onblur(event){stopCalcUpInt(this,this.value);}
In this example, when I alert the ip.onblur I get:
It depends what this is intended to refer to. In an event handler this refers to the element on which the event is being handled. If that's what you want then your code looks good as written; this will point to ip.
If you intend this to refer to the this from outside the event handler and not ip then try this:
var self = this;
ip.onblur = function(event) { stopCalcUpInt(self, self.value); };
The answer to getting this to work was super easy, yet not overly obvious. Instead of:
ip.onblur = function onblur(event){stopCalcUpInt(this,this.value);}
I did this:
ip.setAttribute('onblur','stopCalcUpInt(this,\'' + ip.value + '\');');
Works perfectly... no more banging my head against the wall! Yay!
ip.onblur = function() {stopCalcUpInt(this,this.value);}
ip.onblur is an event handler... i.e. it's a function
Now, when you alert a function, FF will show you the source code for that function (if it's user defined).
That is why you're seeing the plain text of the variable name.
For an event handler, this is the element that is currently handling the event. So, if you're setting the onblur handler of an input box, you will have access to the contents of that input box.
The code sample that you provided:
ip.onblur = function onblur(event){stopCalcUpInt(this,this.value);}
should work correctly. Try
ip.onblur = function onblur(event){alert(this.value); stopCalcUpInt(this,this.value);}
if you want to be sure
Is stopCalcUpInt expecting a number in the second parameter? The value attribute will return a String, while in your hardcoded example you're passing a number type. Try this:
ip.onblur = function onblur(event){stopCalcUpInt(this,this.value * 1);}
As explained in QuirksMode:
Since multiplying assumes numbers,
JavaScript makes the string a number,
if possible.