Reputation: 2448
Suppose I have a html doc with only an h1 and div element. The div is a simple square, made visible with a background color.
If I use the normal way of attaching a click event using JS code only (by using addEventListener), the function fOnClick is correctly executed when ONLY clicking the Div. When clicking the H1 or the document elsewhere, the function is NOT executed, exactly as expected.
But when commenting the dDragger.addEventListener.. line, and uncommenting the MyStuff.Events.bOn.. line (to enable an event handling module), the function fOnClick is also correctly executed when clicking the Div, but is ALSO (Incorrectly!) executed when clicking the H1 or elsewhere in the document !
Am I missing something? Is there a scope that is not caught?
<!DOCTYPE html>
<html>
<head></head>
<body>
<h1>Events</h1>
<div id="dragger" style="width:50px; height:50px; background-color: #444;"></div>
<script>
var MyStuff = MyStuff || {};
MyStuff.Events = (function (oEvents) {
oEvents.bOn = function (oElement, sEventName, fCallback) {
var fListenerMethod = oElement.addEventListener || oElement.attachEvent,
sEventName = oElement.addEventListener ? sEventName : 'on' + sEventName;
return fListenerMethod(sEventName, fCallback) ? true : false;
};
return oEvents;
}(MyStuff.Events || {}));
var fOnClick = function(e) {
e.preventDefault();
console.log("fOnClick");
return false;
};
dDragger = document.getElementById("dragger");
//dDragger.addEventListener("click", fOnClick);
MyStuff.Events.bOn(dDragger, "click", fOnClick);
</script>
</body>
</html>
Upvotes: 1
Views: 42
Reputation: 370759
The problem is here:
return fListenerMethod(sEventName, fCallback) ? true : false;
Returned as is, the fListenerMethod
there (which is the addEventListener
function in modern browsers) is not bound to the element passed in to bOn
. So, it assumes the global calling context, which means that any click anywhere on the document will trigger the event:
addEventListener('click', () => console.log('clicked'))
You should call the function with the appropriate calling context (oElement
) instead:
return fListenerMethod.call(oElement, sEventName, fCallback) ? true : false;
<h1>Events</h1>
<div id="dragger" style="width:50px; height:50px; background-color: #444;"></div>
<script>
var MyStuff = MyStuff || {};
MyStuff.Events = (function(oEvents) {
oEvents.bOn = function(oElement, sEventName, fCallback) {
var fListenerMethod = oElement.addEventListener || oElement.attachEvent,
sEventName = oElement.addEventListener ? sEventName : 'on' + sEventName;
return fListenerMethod.call(oElement, sEventName, fCallback) ? true : false;
};
return oEvents;
}(MyStuff.Events || {}));
var fOnClick = function(e) {
e.preventDefault();
console.log("fOnClick");
return false;
};
dDragger = document.getElementById("dragger");
//dDragger.addEventListener("click", fOnClick);
MyStuff.Events.bOn(dDragger, "click", fOnClick);
</script>
Upvotes: 2