This question already has an answer here:
Why is 'event' variable available even when not passed as a parameter?
(1 answer)
Closed 2 years ago.
I'm developing using mostly Chrome. I just discovered a bug, where the following snippet was working fine in Chrome, but not in Firefox.
Template.myTemplate.events({
"click input[type=checkbox]"(){
let context = event.target.dataset.context;
InspireTheWorldWith.call({context});
}
});
I could not quite believe my eyes, but essentially the variable 'event' was never assigned in the parameters of the event function. Yet this worked in Chrome without any issues. For the record, it clearly should be:
Template.myTemplate.events({
"click input[type=checkbox]"(event, template){
let context = event.target.dataset.context;
InspireTheWorldWith.call({context});
}
});
I'd like to read up more about this to really understand what is going on, but I'm struggling to find the approrpate 'keyword' to google. for.
Any suggestions?
For the record, I'm using Meteor 1.4, babel-runtime#6.18
It's nothing to do with Meteor, just Chrome: Chrome does this to support code written originally for Internet Explorer; in addition to passing the event to the handler, it also sets it as a global event variable.
Microsoft's "new" event handling in IE5 (or was it 5.5?) used a global event object and attachEvent/removeEvent. Then DOM2 came along (after IE6 had been released) and defined addEventListener/removeEventListener where the event handler recieves the event as an argument. Then years passed before Microsoft supported DOM2 (in IE9).
So when Chrome was coming up, they made the decision to provide a global event object to increase compatibility with IE-specific code. Mozilla chose not to originally, but does now; more in my answer here.
You can see it here — run this on Chrome:
document.getElementById("target").addEventListener("click", function(e) {
console.log("e === event? ", e === event);
}, false);
<div id="target">Click me</div>
As you can see, the global event object and the event object the handler receives are the same object.
Related
I have a trouble in this part:
var ex = {
exampl: function(){
var ref=window.event.target||window.event.srcElement; // here
alert(ref.innerHTML); // (example)
}
}
This function is called this way:
document.body.childNodes[0].addEventListener('mouseover',ex.exampl,true);
Only Firefox says that window.event isn't defined...
I don't know what to do, to make it work. It works very well in webkit browsers and opera (I can't check it in MSIE and I don't care about it).
Why does it happen?
try getting the event using the parameter passed (named e in this case). i tested this and both window.event and the e is supported in chrome.
try checking for both, whichever exists
var ex = {
exampl: function(e){
console.log(window.event);
console.log(e);
//check if we have "e" or "window.event" and use them as "evt"
var evt = e || window.event
}
}
window.event is not a feature, it's a bug!
Quoting MDN:
window.event is a proprietary Microsoft Internet Explorer property which is only available while a DOM event handler is being called. Its value is the Event object currently being handled.
And most importantly:
Not part of any specification.
window.event is non-standard, so don't expect any browsers to support it.
First parameter of callback function in element.addEventListener() is an Event object. Use it instead of window.event.
Because window.event doesn't exist in Firefox. That's because browser have different event models and you'll have to deal with their differences or use a library like jQuery not to have to deal with all the differences between browsers. Welcome to the DOM.
Chrome doesn't have it natively either. Rather than having every event trigger pass its own event object, IE dropped properties into window.event and handed that off. This worked since you're only ever dealing with one event at a time. What every browser should have is window.Event which is the actual constructor for event objects. If you're seeing 'window.event' anywhere but IE8 and below, try opening a console on a blank tab and logging or alerting it there. Chances are something is adding it manually on the page you're looking at.
If you look at crossbrowser normalizing code for event handlers, you'll often see:
if(!e){ e = window.event; }
That's event normalizing code handling older versions of IE. In modern browsers, e should be its own object being passed through arguments, not a reference to a property of window.
use jQuery..
let e = $.Event();
https://api.jquery.com/category/events/
window.event is available on Firefox from version 66 (release expected late octobre 2018).
It is said that if we use an event listener as:
document.getElementById("mybtn").addEventListener("click". function(/* event */){...});
then we don't need to mention event parameter inside the function's paranthesis. But if that is true then why don't the following work:
document.getElementById("mybtn").addEventListener("click". function(/* event */){ event.preventDefault()});
This is not true. It can't be implemented like this officially as long as event is not a reserved keyword.
Because people can then do:
document.getElementById("mybtn")
.addEventListener("click",function(troll,event) {
event.preventDefault(); // Boom! error.
});
and complain event is not working. Then it'll become necessary to document how people should not use the event object.
Some browsers might have a global event object. But implementations vary and it's not advisable to rely on such things.
History.
" Some posts say IE allows window.event to accessed without passing event"
When Microsoft corporation reverse engineered JavaScript off Netscape Corporation without consultation, they chose not to implement passing event as a parameter to event handlers.
Instead, IE implemented a window.event property where data for individual events could be accessed. It was during the browser wars when convincing programmers to write code for your browser that failed in the opposition's browser was seen as a good thing. Since JavaScript is single threaded, no re-entrancy problems were created by IE's approach.
You may still see event handler code starting out as
function handler(event)
{ event = event || window.event;
// handler code
}
which is a cross browser way of picking up IE's event object if not supplied to the handler function. At some point IE started passing the event object as a parameter in addition to setting it as a window property to maintain backwards compatibility in their browsers. It certainly works in IE 11 where
<span onclick="alert(arguments[0] === window.event);">click2</span>
alerts "true' when clicked, indicating event is passed as a parameter. In Firefox it is false on the basis window.event doesn't exist.
For current browsers name the first parameter of an event hander as event. If you want to support old versions of IE, use the cross browser code above. Never use 'window.event' by itself.
P.S. Experimenting with document emulation mode in IE11, IE versions <= 8 do not pass event parameter objects to handlers. According to this SO question neither does IE9 in quirks mode. Although IE8 may be the last operable version of IE under Windows XP, the browser is not supported by major commercial web sites in my country (Australia) which forces XP users to upgrade to a different browser. Whatever your case, do not use windows.event by itself.
document.getElementById("mybtn").addEventListener("click", function(event){ event.preventDefault()});
You are passing a callback function to the addEventListener. This function takes a parameter and you're using it.
Maybe changing it to another name and improving the indentation will help you understand this better.
document.getElementById("mybtn")
.addEventListener("click",
function(hello) {
hello.preventDefault()
});
To understand callback functions, try this
If you want use event directly then you have to pass event in that function from where you are calling that function. Otherwise you can create event like this:
document.getElementById("mybtn").addEventListener("click". function(/* event */){
var e=document.getElementById("mybtn");
e.preventDefault()
});
I am using an Event Listener that refer to the relatedTarget variable for Firefox or the toElement variable for Chrome and IE. But since I made that part of the code the parent variable changed. Why?
For example, before today I needed to use evt.Va.toElement to refer to the toElement variable but since this morning I need to use evt.Xa.toElement. Why did it change?
google.maps.event.addListener(polygon,"mouseout",function(evt){ // Mouseout
if(evt.Xa.toElement){ // For Chrome and IE
if(evt.Xa.toElement.id != "idName"){
// Do something
}
} else {
// Do something else
}
}
Is there a way to use toElement or relatedTarget and be certain that it will always work?
evt.Xa is an undocumented property, and shouldn't be used for anything, it could change with any release of the API (the closure compiler reassigns the undocumented properties with each release). Only documented properties are safe to use in production code.
In Firefox and Chrome my code works fine but in IE the event does not get removed.
dojo.connect(d, "onmouseout", function(evt) {
//remove event
});
I've tried:
document.removeEventListener("keydown", keyHandler);
dojo.disonnect(document, "keydown", keyHandler);
document.detachEvent("keydown", keyHandler);
But nothing seems to work. keyHandler is the function which I don't want to execute on keydown when the mouse is out of the canvas stored in variable d.
Managed to get it working with this command: document.onkeydown = null;
Check if you are using the disconnect function properly (and check the spelling/syntax as well). The documentation says:
disconnect() accepts a specially-crafted parameter as it’s only
argument which, coincidentally, is the return value from dojo.connect.
...while you supply 3 parameters to it, the handler being the last one.
As a side note, I am not quite sure about what happens inside Dojo (though it probably implements a polyfill, so you don't have to use native functions if you use Dojo), but IE's attachEvent and detachEvent accepts event names prefixed with 'on', e.g. onmouseout, onkeydown (see the MSDN article).
Also, note the difference in event names. Dojo seems to use IE's syntax with on prefix, while the standard DOM implementation omits it. So, you may want to check if you are binding and unbinding the same event (e.g. if you bind to onkeydown, then you should unbind onkeydown and not keydown).
I am assigning an event handler function to an element through the native browser onclick property:
document.getElementById('elmtid').onclick = function(event) { anotherFunction(event) };
When I'm in anotherFunction(event), I want to be able to use the event object like I would with the event object you get in jQuery through the .on() method. I want to do this because the jQuery event object has properties and methods such as .pageX, .pageY and .stopPropagation() that work across all browsers.
So my question is, after I've passed in the native browser event object into anotherFunction(), how can I turn it into a jQuery event? I tried $(event), but it didn't work.
The obvious question here is: why don't you just use jQuery .on, .bind, .click etc to assign your event handling functions? The answer: I'm building a page that has a huge table with lots of clickable things on it. Unfortunately this project requires that the page MUST render quickly in IE6 and IE7. Using .on et al in IE6 and IE7 creates DOM leaks and eats up memory very quickly (test for yourself with Drip: http://outofhanwell.com/ieleak/index.php?title=Main_Page). Setting onclick behavior via .onclick is the only option I have to render quickly in IE6 and IE7.
Too long for a comment... Because the documentation is a bit vague on this... (I'm looking at 1.7.1 in the following)
jQuery.Event(event, props):
creates a new object
sets its type property to the event's type property.
sets isDefaultPrevented by normalized calls to all the ways to check if default is prevented.
sets originalEvent to reference the event you passed in.
adds an arbitrary set of properties provided by the props object argument.
sets a timestamp.
marks object "fixed".
What you get is basically a new object with a few additional properties and a reference to the original event - no normalization other than isDefaultPrevented.
jQuery.event.fix(event):
ignores objects that have already been marked "fixed".
makes a writable copy (by way of jQuery.Event()) and normalizes the properties mentioned here.
ETA:
Actually, looking closer at the code, jQuery.event.fix() should work - in the way described by #Beetroot-Beetroot. It's all that jQuery does to create the jQuery event object in an event dispatch.
You want jQuery.event.fix.
new jQuery.Event(nativeEvent)
Stores nativeEvent as the originalEvent property.
Handles some bubbling logic.
Timestamps the event
Marks the event as "jQuery's got this"
Gives it all the bubbling/default-preventing functions.
Note at this point the event doesn't have any "eventy" properties, just originalEvent, timeStamp, and the bubbling/default-preventing functions.
jQuery.event.fix(nativeEvent)
Does all the above
Figures out specific fixes ("fix hook") it will need to apply depending on the event type
Copies over a default set of properties from nativeEvent, plus specific ones from the fix hook
Fixes cross-browser issues with the target and metaKey properties
Applies specific cross-browser fixes and normalizations for the fix hook.
Try this:
document.getElementById('elmtid').onclick = anotherFunction;
with:
function anotherFunction(evt){
evt = $.event.fix(evt || window.event);//Note need for cross-browser reference to the native event
...
}
http://jsfiddle.net/Wrzpb/