I have this code:
var bt_empty = document.getElementById("bt_empty");
if(bt_empty)
bt_empty.onclick = emptyCart();
But every time I open the page, the button trigger itself. How can I avoid that?
Thanks
Remove the parenthesis from emptyCart():
bt_empty.onclick = emptyCart;
By including parenthesis, it's executing the function and then assigning the return value to the onclick event, instead of assigning the actual function itself.
The only reason to include the parenthesis would be if the function returns a function. For example:
function emptyCart(){
return function(){
console.log("clicked");
};
}
bt_empty.onclick = emptyCart();
Related
Could someone help to check why the removeHandler is not working? And how to make it work?
Thanks.
<body>
<button onclick="removeHandler()" id="myBtn">remove</button>
<p id="demo">hello</p>
<script>
document.getElementById("demo").addEventListener("click", myFunction("random: "));
function myFunction(t) {
var x = function(){
document.getElementById("demo").innerHTML = t+Math.random();
};
return x;
}
function removeHandler() {
document.getElementById("demo").removeEventListener("click", myFunction("random: "));
}
</script>
</body>
Becasue myFunction returns a new function for each call. Each time you call myFunction, it creates (define) a new function, and return it.
function myFunction() {
return function() {};
}
var f1 = myFunction();
var f2 = myFunction();
console.log(f1 === f2);
FIX:
You have to store the return value of myFunction into a variable, and then pass that variable to both addEventListener and removeEventListener:
var f = myFunction("random: ");
document.getElementById("demo").addEventListener("click", f, false);
// ...
document.getElementById("demo").removeEventListener("click", f);
If you are using React functional component, just be sure to wrap your function inside useCallback hooks, or the function will not be the same after re-rendering. Below is an example that I put the event listener inside useEffect in order to demonstrate re-rendering.
Also make sure that is you are calling another function inside useCallback function, that function should also be wrapped within useCallback to prevent the function from re-initializing.
If these "other function" has dependent on other state, this might cause removeEventListener not working cause the function is re-initialized, which the reference of that function is not the same.
const test = useCallback(() => {...}, [])
useEffect(() => {
if (isTest) document.addEventListener('mousemove', test, true)
else document.removeEventListener('mousemove', test, true)
}, [isTest])
JavaScript is very particular when it comes to removing event listeners. You can only remove the same event listener that you have previously added. It also needs to match whether it’s bubbling.
Among other things, that means that you cannot remove an anonymous event listener since you have no way of identifying it.
In your case, you’re compounding the problem by actually attempting to remove a newly created event listener.
The only way to remove an event listener is to ensure that it has a name. In your case, it would be as follows:
var random=myFunction("random: ");
document.getElementById("demo").addEventListener("click", random,false);
function myFunction(t) {
var x = function(){
document.getElementById("demo").innerHTML = t+Math.random();
};
return x;
}
function removeHandler() {
document.getElementById("demo").removeEventListener("click", random,false);
}
Note:
There is a variable name (random in this case) to identify the event listener function
I have also added false as a third parameter to ensure that the remove matches the add.
It seems every time you click on demo function call return new function so that its not behaving as expected.
try running Example
<body>
<p id="demo">Hello</p>
<button onclick="removeHandler()" id="myBtn">Try it</button>
<p><strong>Note:</strong> The addEventListener() and removeEventListener() methods are not supported in Internet Explorer 8 and earlier versions.</p>
<script>
document.getElementById("demo").addEventListener("click", myFunction);
function myFunction() {
document.getElementById("demo").innerHTML = Math.random();
}
function removeHandler() {
document.getElementById("demo").removeEventListener("click", myFunction);
}
</script>
I have this simple function that copies some html, and places it in another div.
If I put the code for the function in the click event it works fine, but when I move it into a function (to be used in multiple places) it no longer works.
Do you know why this is?
If I console.log($(this)); in the function it returns the window element.
function addHTMLtoComponent () {
var wrapper = $(this).closest(".wrapper");
var component = $(wrapper).find(".component");
var componentCodeHolder = $(wrapper).find('.target');
$(componentCodeHolder).text(component.html())
//console.log($(this));
}
$(".js_show_html").click(function () {
addHTMLtoComponent();
});
codepen here - http://codepen.io/ashconnolly/pen/ebe7a5a45f2c5bbe58734411b03e180e
Should i be referencing $(this) in a different way?
Regarding other answers, i need to put the easiest one:
$(".js_show_html").click(addHTMLtoComponent);
since you called the function manually the function doesn't know the "this" context, therefore it reverted back to use the window object.
$(".js_show_html").click(function () {
addHTMLtoComponent();
});
// Change to this
$(".js_show_html").click(function () {
// the call function allows you to call the function with the specific context
addHTMLtoComponent.call(this);
});
Ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call
this in the context of the click() event is the element clicked. In the context of the function addHTMLtoComponent this no longer is a reference to the element clicked.
Try passing the clicked object to the function to maintain the object reference.
function addHTMLtoComponent ($obj) {
var $wrapper = $obj.closest(".wrapper");
var $component = $wrapper.find(".component");
var $componentCodeHolder = $wrapper.find('.target');
$componentCodeHolder.text($component.html());
}
$(".js_show_html").click(function () {
addHTMLtoComponent($(this));
});
The special keyword this, when you call a function by itself, is the window object (which is what you observed). For the behavior you need, just add a parameter to the function that loads the appropriate context:
function addHTMLtoComponent(context) {
var wrapper = $(context).closest(".wrapper");
var component = $(wrapper).find(".component");
var componentCodeHolder = $(wrapper).find('.target');
$(componentCodeHolder).text(component.html())
//console.log($(context));
}
$(".js_show_html").click(function() {
addHTMLtoComponent(this);
});
One thing you could consider is that addHTMLtoComponent() could be made into a jQuery function itself:
$.fn.addHTMLtoComponent = function() {
return this.each(function() {
var wrapper = $(this).closest(".wrapper");
var component = $(wrapper).find(".component");
var componentCodeHolder = $(wrapper).find('.target');
componentCodeHolder.text(component.html())
});
}
Now you can call it like any other jQuery method:
$(".js_show_html").click(function () {
$(this).addHTMLtoComponent();
});
The value of this in a jQuery method will be the jQuery object itself, so you don't need to re-wrap it with $(). By convention (and when it makes sense), jQuery methods operate on all elements referred to by the root object, and they return that object for further chained operations. That's what the outer return this.each() construction does.
Inside the .each() callback, you've got a typical jQuery callback situation, with this being set successively to each member of the outer jQuery object.
You have to pass the element as parameter to this function.
eg:
<div onclick="addHTMLtoComponent ($(this))"></div>
I'm sure this should be a simple question but I'm still learning so here it goes:
I have some code to run a function on click to assign the clicked element's ID to a variable but I don't know how to pass the "this.id" value to the namespace without making a global variable (which I thought was bad).
<script>
fsa = (function() {
function GetTemplateLoc() {
templateId = document.activeElement.id;
alert(templateId + templateId2);
}
return {
GetTemplateLoc: GetTemplateLoc,
}
})();
//call the functions
$(document).on('click', '.template', function () {
fsa.GetTemplateLoc();
});
</script>
and HTML with random picture:
<img id="template-1" class="template" src="http://fc02.deviantart.net/fs70/f/2010/028/c/b/cb21eda885b4cc6ee3f549a417770596.png"/>
<img id="template-2" class="template" src="http://fc02.deviantart.net/fs70/f/2010/028/c/b/cb21eda885b4cc6ee3f549a417770596.png"/>
The following would work:
var fsa = (function() {
function GetTemplateLoc() {
var templateId = this.id;
alert(templateId);
}
return {
GetTemplateLoc: GetTemplateLoc,
}
})();
//call the functions
$(document).on('click', '.template', fsa.GetTemplateLoc);
jQuery generally calls functions you pass as event handlers with this set to the DOM object the event is associated with.
In this case it will call GetTemplateLoc() with this set to either .template element, so you can use this directly in the function and don't need to pass any parameters.
Important tip: Always declare variables using var. JavaScript has no automatic function-local scope for variables, i.e. every variable declared without var is global, no matter where you declare it. In other words, forgetting var counts as a bug.
Try this : You can directly use this.id to pass id of the clicked element where this refers to the instance of clicked element.
<script>
fsa = (function() {
function GetTemplateLoc(templateId ) {
//templateId = document.activeElement.id;
alert(templateId + templateId2);
}
return {
GetTemplateLoc: GetTemplateLoc,
}
})();
//call the functions
$(document).on('click', '.template', function () {
fsa.GetTemplateLoc(this.id);
});
</script>
If you're able to use jQuery within the GetTemplateLoc function, you could do something like this:
var fsa = (function() {
function GetTemplateLoc($trigger) {
var templateId = $trigger.attr('id'),
templateId2 = $($trigger.siblings('.template')[0]).attr('id');
alert(templateId + ' ' + templateId2);
}
return {
GetTemplateLoc: GetTemplateLoc,
}
})();
$(document).on('click', '.template', function () {
fsa.GetTemplateLoc($(this));
});
You can set GetTemplateLoc to expect a jQuery object as a parameter (the dollar sign at the beginning of $trigger can be used to distinguish it as a jQuery object rather than any other data type, it's not necessary but can help clarify things sometimes).
templateId will store the value of the clicked image's ID, and templateId2 will store the value of the other image's ID. I also added a space between the two variables in the alert.
If you can't use jQuery within GetTemplateLoc, you could do something like this:
var fsa = (function() {
function GetTemplateLoc(trigger) {
var templateId = trigger.id;
var templateId2 = trigger.nextElementSibling == null ? trigger.previousElementSibling.id : trigger.nextElementSibling.id;
alert(templateId + ' ' + templateId2);
}
return {
GetTemplateLoc: GetTemplateLoc,
}
})();
This time, the .template that triggered the event is passed into GetTemplateLoc, but this time it's not a jQuery object. templateId is assigned to the trigger's ID and then templateId2 is assigned in a ternary. First, the nextElementSibling of trigger is checked to see if it's null. If it is, we know that trigger is the second of the two .template elements. Therefore we can set templateId2 to the ID of trigger's previous sibling. If trigger's nextElementSibling is not null, then we know that trigger is the first template and we populate templateId2 with the ID of nextElementSibling. This exact method will only work with two .template's, if there are more you'll need some additional/different logic, probably to retrieve all .template IDs and then loop through them to add them to the alert message. Hope this helps.
How can I pass parameters to a function declared like something = function(){};
window.prototype.initInterface = function(){
this.mainPane = document.createElement('div');
this.mainPane.style.border="5px solid grey";
this.mainPane.style.margin="0px";
this.mainPane.style.width="420px";
this.mainPane.style.height="600px";
this.exitButton = document.createElement('input');
this.exitButton.setAttribute("type", "button");
this.exitButton.setAttribute("value", "exit");
this.exitButton.onclick = function(){
document.body.removeChild(this.mainPane);
};
this.mainPane.appendChild(this.exitButton);
document.body.appendChild(this.mainPane);
}
When the user presses the exit button I want to remove the mainPane from the body of the html page.
this.exitButton.onclick = function(this.mainPage){
document.body.removeChild(this.mainPane);
};
Does not work
How can I do this?
For your exitButton.onclick function to have access to variables you create in the enveloping initInterface function you want a to create a closure in the exitButton.onclick function by returning a function that performs the action you want and passing that the variable.
exitButton.onclick = function () {
return (function() {
document.body.removeChild(mainPane);
})(mainPane);
};
Read more on how closures work here and here and see a working example fiddle.
Alternatively, you forget about closures and walk up the DOM from the button which triggers the event to your mainPane
exitButton.onclick = function() {
// in here "this" is the object that triggered the event, exitButton
document.body.removeChild(this.parentNode);
}
As an aside, window.prototype does not exist if you are doing this in a browser; window is the object at the top of prototype chain in browser scripting. You want just window.initInterface = function () {} which is the exact same thing as function initInterface() {} because everything you do in javascript in the browser becomes a property of window.
This function is the function w/o function name. It could only be used once and you may not easy to find out what parameters should be passed.
You can create another function like :
function go(a1){}
And call it like window.prototype.initInterface = go(a1);
Or you can get some DOM parameters in this unnamed function by using functions like getDocumentById("DOM ID") etc.
I'm creating a button dynamically using JavaScript and at the same time assigning attributes such as 'ID', 'type' etc and also 'onclick' in order to trigger a function.
All works fine apart from the assignment of the 'onclick'. When clicked, the button is not triggering the function as it is supposed to. the function I'm trying to run is 'navigate(-1)' as seen below.
Where am I going wrong?
Here's my code:
function loadNavigation() {
var backButton;
backButton = document.createElement('input');
backButton.ID = 'backButton';
backButton.type = 'button';
backButton.value='Back';
backButton.onclick = 'navigate(-1)';
document.body.appendChild(backButton);
}
As the other said you should assign a function.
Just wanted to point out that in this case you want to pass a value so you need to assign an anonymous function (or a named function defined inline) like
button.onclick = function() {otherfunction(parameter)};
If the function you want to assign does NOT require a parameter you can use it directly
button.onclick = otherfunction;
Note that there is no parenthesis in this case
button.onclick = otherfunction(); // this doesn't work
won't work as it will call otherfunction as soon as it is parsed
you are assigning text to the onclick, try assigning a function.
backButton.onclick = function(){navigate(-1);};
You have to assign a function, not a string.
backButton.onclick = function wastefulDuplicationOfBackButton () {
navigate(-1);
}
Use a function instead of a string. For example,
backButton.onclick = function () { navigate(-1); };
You should assign a function, not a string:
//...
backButton.onclick = function () {
navigate(-1);
};
//...
backButton.onclick = function() { navigate(-1); }
In case this question is passed as a dupe, here is how to do it in current browsers
ES6
backButton.addEventListener("click",() => history.back());
Older but newer than onclick
backButton.addEventListener("click",function() { history.back() });