unable to register onclick with addEventListener - javascript

I'm just trying to to register onclick for div, but it's not working. Instead, the cal to alert is getting triggered when page is loaded.
function print()
{
alert(' div clicked..');
}
var divElement = document.getElementById("content");
divElement.addEventListener("onclick", print());
Here's a jsFiddle.

The problem is you do not need the on prefix. And print should not have empty parenthesis. An empty parenthesis will cause the function to execute, and its return value be passed as the function to call - which is not what you want.
Try this:
var divElement = document.getElementById("content");
divElement.addEventListener("click", print);
Here's an updated working jsFiddle.
Edit: Per Ian's comment below, here's a helper function for backwards compatibility with certain version of Internet Explorer.
function AttachEventListener(element, event, handler) {
if (element.addEventListener) {
element.addEventListener(event, handler, false);
} else if (element.attachEvent) {
element.attachEvent('on' + event, handler);
} else {
alert('Invalid element specified for AttachEventListener');
}
}
Instead of using divElement.addEventListener("click", print), you would do AttachEventListener(divElement, 'click', print).
The main reason to use the helper function is because older versions of Internet Explorer do not have addEventListener, and do require the on prefix when using attachEvent. This helper function will save you the trouble of doing the feature-check yourself on every event binding.

You should write it like this:
divElement.addEventListener("click", print);
print is a variable that points to your function.
print() is the output of that function. (it has no output, so it's undefined)
Since you want to assign the function, not the output, you must use print.
Also, you don't need the on prefix.
Presto: http://jsfiddle.net/AEjKC/

Related

Javascript: Stop onClick default

I get the feeling I am missing something obvious but just can see it.
A trigger on the click event is set:
anchor.addEventListener("click", myClickEvent );
function myClickEvent() {
this.preventDefault(); // fails
return false;
}
However the default onClick method still happens.
Can I cancel default propogation at the same time as I addEventListener or is there some other way of doing this. I cannot use .preventDefault() from within myClickEvent because the event is not available at that point.
Edit following comments for clarity:
The default onClick of the tag happens even though myClickEvent returns false.
element.addEventListener("click", myClickEvent );
function myClickEvent(event) {
event.preventDefault();
return false;
}
Returning false from a handler that was registered with addEventListener does nothing. See https://stackoverflow.com/a/1357151/227299 and https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault
The recommended way is to call event.preventDefault()
function myClickEvent(e) {
e.preventDefault()
}
Handlers from HTML attributes still work, but you should not use it since it's not as clear what return false means when compared to event.preventDefault() (not allow the link to be followed) and event.stopPropagation() (don't let the event bubble up)
There is no such function in the global scope called preventDefault -- you need to use the event that has been passed into your callback.
Also please make sure that you are attaching the event to something that can be clicked on (a form, anchor, button etc) that can potentially have an event prevented.
If you attach the event to a child/parent element nothing will work as you expected.
Nearly there thanks to Teemu's code but not quite.
There is a difference depending on how the function is called. Seemingly there is both a hidden parameter sent defining the value of 'this' and when called without parameters an automatic event object sent as the first visible parameter:
Call it without parameters:
anchor.addEventListener("click", myClickEvent );
function myClickEvent(param1, param2) {
// this = events parent element (<a>)
// this.href = <a href=...>
// param1 = event object
// param2 = undefined
oEvent = param1;
oEvent.preventDefault();
}
but then call it with parameters:
anchor.addEventListener("click", function (oEvent) { myClickEvent(oEvent, myParameter); });
function myClickEvent(param1, param2) {
// this = [object Window]
// this.href = undefined
// param1 = event object
// param2 = myParameter
oEvent = param1;
oEvent.preventDefault();
}
Notice how when parameters are sent manually the value of 'this' changes from the events parent element to '[object Window]', causing this.href to go wrong.
However the preventDefault now appears to be working reliably.

is this a valid way to define an explicit function inside addEventListener?

Just wondering, is this a valid way to define an explicit function inside JavaScript's addEventListener function so that it could be removed at any time using removeEventListener?
var somefunction;
window.addEventListener('load', somefunction = function(){
//do something
}, false);
window.removeEventListener('load', somefunction, false);
In other words, is it ok to define a variable somefunction and then assign an anonymous function to it inside addEventListener, instead of defining somefunction outright from the get go? It seems to work in FF and Chrome, but just wanna make sure this is officially valid JavaScript syntax.
Yes, it will work. An assignment is an expression -- it assigns to the variable and also returns the value that it assigned.
Personally I think this is a confusing way to write it. If you're refer to the function by name, put the definition where you define the name, not where you use it. In particular, if you try to do this twice, you'll have a problem because each event listener will have a different function, but it has the same name.
window.addEventListener('event1', somefunction = function() {
//do something
});
window.addEventListener('event2', somefunction = function() {
//do something
});
Now you can only remove event2, because somefunction no longer refers to the function that was added to event1.
Calling removeEventListener() with arguments that do not identify any
currently registered EventListener on the EventTarget has no effect.
So as long as removeEventListener has say a 'click' event as an argument, any one eventListener registered to the 'click' event will be removed. This is evident in OP's case, therefore it is feasible according to the criteria previously mentioned.
The following Snippet demonstrates a registered eventListener added to #target1 to listen for the 'click' event. It will be functional until removeEventListener() is called to remove the eventListener within 4 seconds. Notice that this particular removeEventListener's arguments are:
the event object............: click
a named function..........: eventLog()
and it's capture boolean: false
The identifying argument is 'click' and the target.event is #target that allows removeEventListener() to identify it's target.
SNIPPET
var eventLog;
var tgt1 = document.getElementById('target1');
var term = document.getElementById('btn');
tgt1.addEventListener('click', eventLog = function(e) {
console.log('target1 has been clicked');
}, false);
setTimeout(function() {
tgt1.removeEventListener('click', eventLog, false);
eventLog('Target1 eventListener is removed');
}, 4000);
function eventLog(str) {
console.log(str);
}
#target1 {
border: 2px solid red;
}
<p>Start clicking TARGET1 several times and you'll notice that each `click` event is firing as displayed in the console. Within 4 seconds, TARGET1's eventListener should be removed.</p>
<div id='target1'>TARGET1</div>

Javascript addEventListener and removeEventListener with partial function

I want to create javascript function adds an event listener to a div such that when the div is clicked, it runs a function, and ensures that the div can only be clicked once. My function looks like this right now:
function clickOnce(divID,func){
var args = Array.prototype.slice.call(arguments,2);
functionToRun=partial(func,args);
thisDiv=document.getElementById(divID);
thisDiv.addEventListener("click",function(e){
e.target.removeEventListener(e.type, arguments.callee);
functionToRun();
});
}
I have a working example in jsfiddle: https://jsfiddle.net/qtzLhgr4/1/
In the JSfiddle, when I click button 1 it says "button #2 clicked".
You didn’t declare functionToRun, so it’s implicitly global. Declare it and thisDiv:
var functionToRun=partial(func,args);
var thisDiv=document.getElementById(divID);
Then start working in strict mode, which will prevent these kinds of problems as well as stop you from using arguments.callee, which is the Wrong Way To Do Things:
thisDiv.addEventListener("click", function listener(e) {
thisDiv.removeEventListener("click", listener);
functionToRun();
});
(e.target was also incorrect; this would have been better.)
functionToRun (and thisDiv, but that's not related to the problem) is global. The second call to clickOnce overwrites functionToRun, so both event handlers execute the same function.
Always declare your variables. Also note that arguments.callee is deprecated. You can use a named function expression instead.

Object doesn't support property or method 'attachEvent' in ie8 when attackhing an even

I still need a vanilla JavaScript solution to attach an event handler in Internet Explorer 8. When I do below code I got an error in ie8 saying Object doesn't support property or method 'attachEvent'. How should I fix this.
if ('addEventListener' in document) {
document.addEventListener('DOMContentLoaded', function () {
[].forEach.call(document.querySelectorAll('input'), function (el) {
el.addEventListener('click', function (e) {
e.preventDefault();
alert('nope');
}, false);
});
})
}
else
{
var d = document.getElementsByTagName('input');
d.attachEvent('onclick', function () {
alert('no');
});
}
getElementsByTagName returns a collection of elements, not a single element. The collection doesn't have attachEvent. The individual elements do (on older IE).
Note also that:
Your IE-specific branch doesn't wait for the full DOM to be parsed as your standards branch does. Either both should, or both should not, but not a mix. Best practice is not to use DOMContentLoaded and just put the script at the end of the HTML, immediately prior to the closing </body> tag.
Your IE event handler isn't preventing the default action, whereas your standards one is.
If you want a cross-browser event attaching function, here's one in another answer on SO.

Access event object in event handler

When I try to attach event handler functions with parameters like :
myhandle.onclick = myfunction(param1,param2);
function myfunction(param1,param2){
}
Now I want to access the event object in my handler function. There is an approach mentioned on the web of sending event object, like:
myhandle.onclick = myfunction(event,param1,param2);
But its giving event object undefined when I test it out.
I know libraries make this stuff easy but I am looking for a native JS option.
myhandle.onclick = myfunction(param1,param2);
This is a common beginner error at a JavaScript level, and not something that libraries can really fix for you.
You are not assigning myfunction as a click handler, you are calling myfunction, with param1 and param2 as arguments, and assigning the return value of the function to onclick. myfunction doesn't return anything, so you'd be assigning undefined to onclick, which would have no effect..
What you mean is to assign a reference to myfunction itself:
myhandle.onclick= myfunction;
To pass the function some extra arguments you have to make a closure containing their values, which is typically done with an anonymous inline function. It can take care of passing the event on too if you need (though either way you need a backup plan for IE where the event object isn't passed as an argument):
myhandle.onclick= function(event) {
myfunction(param1, param2, event);
};
In ECMAScript Fifth Edition, which will be the future version of JavaScript, you can write this even more easily:
myhandle.onclick= myfunction.bind(window, param1, param2);
(with window being a dummy value for this which you won't need in this case.)
However, since many of today's browsers do not support Fifth Edition, if you want to use this method you have to provide an implementation for older browsers. Some libraries do include one already; here is another standalone one.
if (!('bind' in Function.prototype)) {
Function.prototype.bind= function(owner) {
var that= this;
var args= Array.prototype.slice.call(arguments, 1);
return function() {
return that.apply(owner,
args.length===0? arguments : arguments.length===0? args :
args.concat(Array.prototype.slice.call(arguments, 0))
);
};
};
}
I'm not entirely sure what you're trying to do, but perhaps something like this is what you're looking for?
function myfunction(param1, param2){
return function(event) {
// For compatibility with IE.
if (!event) {
event = window.event;
}
alert("event = " + event + ", param1 = " + param1 + ", param2 = " + param2);
};
}
myhandle.onclick = myfunction(param1, param2);
The end result of this is that the anonymous function inside of myfunction will be called as the onclick handler, resulting in the event plus the two parameters being printed. The two parameters are fixed at the time that the event handler is added while event will change each time the user clicks on myhandle.
Try this:
if (!event) { event = window.event; }
inside of myfunction().

Categories