Anything that stands out why this would break in firefox like this - javascript

Anything that stand out why this would break in firefox like this:
var test = ko.dataFor($(event.target).closest('blah')[0]);
The error message is:
ReferenceError: event is not defined.
Doesn't happen for IE or Chrome.

IE originally had a global event object, meaning it would be available without naming the argument
element.addEventListener('click', function() {
console.log(event); // would be the object in IE
});
All though this is not really standard behaviour, Chrome decided to implement this as well.
In Firefox however, event would be undefined in the above code, and the argument would have to named, as in
element.addEventListener('click', function(event) {
console.log(event); // works everywhere, ^ becase it's there
});
This is how it should be done, without relying on the global event object

Related

Why do many pass an event in the callback

I recently learned that you don't have to pass the event as a parameter for an event. But I wonder why many still pass the event.
Example click event
btn.addEventListener("click", myfn.bind());
function myfn(event) {
console.log(event.target);
console.log(this);
}
Is there a reason for this? Because that works to:
btn.addEventListener("click", myfn.bind());
// without passing event
function myfn() {
console.log(event.target);
console.log(this);
}
btn.addEventListener("click", myfn.bind());
// without passing event
function myfn() {
console.log(event.target);
console.log(this);
}
Above works because event can access through a global variable, window.event
The read-only Window property event returns the Event which is
currently being handled by the site's code. Outside the context of an
event handler, the value is always undefined.
function myfn(anotherArgName) {
console.log(anotherArgName === window.event); // true
}
Not recommend to use the 2nd one as MDN docs says,
Deprecated: This feature is no longer recommended. Though some
browsers might still support it, it may have already been removed from
the relevant web standards, may be in the process of being dropped, or
may only be kept for compatibility purposes. Avoid using it, and
update existing code if possible; see the compatibility table at the
bottom of this page to guide your decision. Be aware that this feature
may cease to work at any time.
Plus depending on external dependencies makes your function hard to read, test & maintain.

TypeError: Can only call Node.addEventListener on instances of Node on Safari

I have this piece of code in my React component that disables the "enter" key.
export const attachDisableEnterEvent = (ref) => {
const node = ReactDOM.findDOMNode(ref);
// Evergreen event listener || IE8 event listener
const addEvent = node.addEventListener || node.attachEvent;
addEvent('keypress', _disableEnter, false);
}
It works fine on Chrome / Firefox, but not Safari. On Safari I get :-
TypeError: Can only call Node.addEventListener on instances of Node
I could only get it to work (on all fronts) by doing this :-
addEvent.call(node, 'keypress', _disableEnter, false);
Just wondering why is the implementation for addEventListener different on Chrome & Safari. It seems like Node.addEventListener on Chrome will just intuitively bind this to the node instance that defined it.
It's probably the same reason why we have the following:
var log = console.log;
log('foo') // TypeError
Instead, we have to:
var log = console.log.bind(console); // bind console.log function to it's proper context
log('foo') // 'foo'
In your case, calling
addEvent('keypress', _disableEnter, false);
causes the context to be the window object (implicitly).
In general you always want to bind your function first to the owning object when you intend to pass it off to someone else. Browser implementations are different for each browser, so that is the best way to ensure that it works uniformly.
In the console case, I believe that .log refers to other instance methods on the console object itself. And so in Safari, the node.addEventListener function may be implemented in a way that needs other functions only defined on node, and they probably threw in a more descriptive error message as well.
So instead you should do:
const addEvent = node.addEventListener || node.attachEvent;
const boundAddEvent = addEvent.bind(node);
// use boundAddEvent however you like anywhere, or .call like you did

Why is there an 'event' variable available without being defined when there was an event upstream?

I stumbled across an odd behaviour today. Basically, I had a function bound to a knockout.js click event. The function was making use of the knockout event, but was not explicitly taking it as an argument.
this.myClickHandler = function(){
console.log(event); //event gets logged in Chrome/IE11, not Firefox
}
This looked weird to me, but in Chrome it was working as expected. It also worked correctly in IE11. In Firefox however, it did not function. As soon as I explicitly it worked in all browsers. This is what I would expect would be needed for it to work at all.
this.myClickHandler = function(model, event){ //event is second parameter passed from knockout click event
console.log(event); //event gets logged in all browsers
}
I had a play around and reproduced this with jQuery as well
function func(){
alert(event);
}
function runFunc(callback){
callback();
}
$(document).ready(function(){
runFunc(func);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
So how is this working? Why do I have access to a variable called 'event' in some browsers but not others? Is this intended behaviour?
It is something that got carried from the old version of IE, where the event object was not passed to the handler method instead it was set in the global context.
For backward compatibility IE still supports this model and chrome also has added support for this feature. But FF is not supporting it.
Event object references

JavaScript error "Function is expected"

I have several listeners like this, which listen to click and then displays content within <div id="c50"><a hre...>CONTENT</a></div> (in this case). Everything works in Opera, Chrome and FF, but not in IE.
google.maps.event.addListener(pano50, 'click', function() {
fireEvent(document.getElementById("c50").getElementsByTagName("a")[0], 'click');
})
Chrome javascript console tool displays this error after click (but works fine):
Uncaught TypeError: object is not a function
but traditionally, IE8 displays:
Function expected on line 817
which is the first line of code above and do nothing after click. Thank you for any advice!
EDIT: here is the fireEvent function:
function fireEvent(element, event) {
if (document.createEventObject){
/* for IE */
return element.fireEvent('on' + event, document.createEventObject());
}else{
/* for other browsers */
var evt = document.createEvent('HTMLEvents');
evt.initEvent(event, true, true);
}
return !element.dispatchEvent(evt);
}
You've got MooTools running on your page. MooTools overrides IE's built-in element.fireEvent() method with its own normalized method that works for all browsers. MooTools' version of fireEvent() expects "click" instead of "onclick".
You can fix this one issue by simply changing your fireEvent function to use "click" instead of "onclick":
/* for IE */
return element.fireEvent(event, document.createEventObject());
But, since MooTools normalizes element.fireEvent to work with all browsers, you may be able to ditch your fireEvent function, and instead just call element.fireEvent() directly.
You may have bigger problems. You are using MooTools and jQuery side by side which is ok, but if you don't know what you are doing, you can get into trouble quickly.
It's possible it's complaining because
document.getElementById("c50").getElementsByTagName("a")[0]
is not a function. Where is the fireEvent function coming from?

JavaScript event handlers -why no alert?

I'm a newbie at JavaScript trying to learn event handlers. Looking at this fiddle http://jsfiddle.net/mjmitche/uV4kv/ can anyone tell me why the pop up is not appearing when the link is clicked?
I've also copied the code below
click me
function addEventHandler(oNode, sEvt, fFunc, bCaptures){
if (typeof(window.event) != "undefined")
oNode.attachEvent("on"+sEvt, fFunc);
else
oNode.addEventListener(sEvt,fFunc,bCaptures);
}
function onLinkClicked(e) {
alert("you clicked the link");
}
function setUpClickHandler(){
addEventHanlder(document.getElementById('clickLink'), "click", onLinkClicked, false);
}
addEventHandler(window,"load",setUpClickHandler,false);
There are basically three problems:
You have some typos, e.g. "Hanlder" instead of "Handler" and "Sevt" instead of "sEvt".
The code is already run after page load, so the event handler you add to window will never be called. Change in jsFiddle from onLoad to no wrap (head).
You "IE detection" does not work. I get this error in Chrome:
Uncaught TypeError: Object http://fiddle.jshell.net/_display/# has no method 'attachEvent'.
Better would be to test whether the function window.attachEvent exists. I also think that window.event is only available when an event is raised.
If this is corrected, your code will run (DEMO).
Further notes:
Testing which method is supported (i.e. attachEvent or addEventListener) on every call of your function is unnecessary. It won't change during the life of the page. Better is to test only once at the beginning. Example:
var addEventHandler = (function() {
if(window.attachEvent) {
return function(oNode, sEvt, fFunc) {
oNode.attachEvent("on"+sEvt, fFunc);
};
}
else {
return function(oNode, sEvt, fFunc, bCaptures) {
oNode.addEventListener(sEvt,fFunc,bCaptures);
};
}
}());
This assigns a function the supported function to addEventHandler.
A couple of problems:
You have a recurring typo, "Hanlder" instead of "Handler". There are at least two, one where you do your setUpClickHanlder (sic) function, and one within it (addEventHanlder).
Also, you have "Sevt" where you mean "sEvt". (JavaScript is case sensitive.)
Let tools help you. Use a browser that gives you a console showing errors. Use a debugger for single-stepping through code, looking at variable values at runtime with inspectors, etc.
Your addEventHandler needs adustment:
function addEventHandler(oNode, sEvt, fFunc, bCaptures) {
oNode.attachEvent ? oNode.attachEvent ("on" + sEvt, fFunc) :
oNode.addEventListener (sEvt, fFunc, bCaptures);
}
It is in event handlers themselves that you need to check for window.event

Categories

Resources