SVG <use> element not inheriting event handlers in Firefox? - javascript

EDIT: This is a bug in Firefox, and cannot be resolved without editing Firefox directly, which I have no desire to do. I consider this question resolved for the purpose of asking other people for he.
I am trying to create a pixel-based drawing program using SVG. I initialize the event handlers on a couple of <polygon>s inside a <defs>, and then copy that a bunch of times with <use>s to make the the canvas, and it works fine, in Chrome.
But regardless of whether I assign the .onclick attribute or use .addEventListener, my <use>s don't register anything in Firefox. As I was researching solutions for this, I found another thematically, and possibly technically, related phenomenon: <use>s copied using .cloneNode also do not retain event listeners. I could assign each <use> element the event listeners as I generate them, but it seems to me that that is the least desirable solution.

The only solution I came up with is to register the same event listener on the use element. After that it works in Firefox, but not anymore in IE, Safari and Chrome, because the event gets fired twice. Therefore you have to de-register the event of the copied SVG element. It is a workaround, but no good solution. I hope someone else can give a better answer for that.

Related

document.querySelectorAll with the pseudo-class :hover not working in FF or IE

I want to get the element under the cursor. When I use document.querySelectorAll(":hover");, it works well in Chrome but it doesn't work in Firefox or IE.
It might be because I use it inside a eventListener in a Google maps. Here how I use it.
google.maps.event.addListener(polygon,"mouseout",function(){
elementHover = document.querySelectorAll( ":hover" );
alert(elementHover[elementHover.length-1].id);
});
In Chrome it gives me the id of the element I'm hovering with the cursor, but I get nothing in IE or FF.
Is there a reason you're using mouseout instead of mouseover? It seems like, depending on how the browser resolves it (does it fire the event before you leave, or just after you leave, the object that is listening for the event?) that could cause some consternation. Is there a reason you're not just passing in the Event object to get the object you're leaving, rather than hoping that a selector will fire?
According to Google's docs (https://developers.google.com/maps/documentation/javascript/events#EventArguments), you can pass the event object into the function:
google.maps.event.addListener(polygon,"mouseout",function(evt){
// get the target from the mouseout event, something like this:
elementHover = evt.target;
alert(elementHover[elementHover.length-1].id);
});
I can't test this at the moment, so you'll probbly have to fiddle with it and read into Google's docs to make sure that the event you're looking at gives you a reference to the object that it came from (you might even be able to use "this" instead of evt.target, depending on what gets passed into context). However, :hover is still a semi-flighty beast, and depending on the order in which events are resolved, it's quite possible that you only see it in Chrome because it fires off the events differently than FF and IE.
Good luck!

Setting event handlers to DOM objects

I was looking for the most proper way to attach DOM events avoiding browser compatibility issues and found that the Mozilla developers site states:
The old way is to just assign it like this:
document.getElementById('cupcakeButton').onclick = getACupcake;
As above, the event object is either a global or an argument. This
method may have problems and is not the preferred method, but it still
works and a lot of people still use it.
What type of problems does this refer to?
The most obvious one is already mentioned, it would replace a previously assigned handler.
document.getElementById('id') should work in all browsers except in really old ones (Netscape 4-, IE 4-), there you should use document.layers['id'] and document.all[id] respectively.
IE 5 up to IE 7 have one more issue, which is that they will also return elements where name='id' instead of only the elements where id='id'. That could really stuff you up.
Have a look at jQuery for a way to attach DOM event handlers avoiding browser compatibility issues.
The biggest problem I can think of is that it won't allow assigning multiple click handlers, by doing another .onclick = fn; you basically unbind the previous handler if it was there.
Even if that magically worked, you would have no way to unregister a specific handler; it's all or nothing.

DOM Changed Event Firefox Extension

So I have created a Firefox extension and it works great, however when I submitted it (although it was accepted) it came up with one security warning. It said setTimeout() was removed in an else clause.
So, is there a way to listen for any DOM change? (or even a specific element changing, I have an ID for both). However, divs do not have an onChange event so any ideas?
I don't mind if it's ANY change, doesn't have to be div-specific.
DOMSubtreeModified event sound like something you want to use. Keep in mind, that it is deprecated and after some time its support will probably be removed from browsers.
http://help.dottoro.com/ljrmcldi.php
It turns out adding an "onChange" event to a div works fine, although it might not be W3C valid it doesn't really matter as it's only a Firefox extension (plus it works!).

Getting back the event handler returns undefined

The following codes don't work:
function dnd(){
}
var ele = document.getElementById("relative");
ele.addEventListener("click",dnd,false);
document.write(ele.onclick);
the output is undefined. I guess the output should be function onclick(event){dnd();}
What should I do to solve this problem?
Any suggestion is appreciated.
There are 3 common ways to attach events to DOM nodes.
The addEventListener() method is the way to register an event listener as specified in W3C DOM. It has many benefits, but doesn't work in Internet Explorer. For Internet Explorer you'd have to use the attachEvent() method, which offers similar functionality.
On the other hand, the onclick property is an older, but more supported way to attach event handlers. However it has certain disadvantages, such as allowing just one event handler for each event.
As for how to get back the event handlers that are attached to a particular node, it depends on the method you use to attach the events. The problem with your example is that you're using the addEventListener() method to attach the event, and then trying to read it using the onclick property.
You may want to check out the following Stack Overflow post for further reading into this topic, especially the post by #Crescent Fresh:
How to find event listeners on a DOM node?
The onclick property is only going to show you an event handler if it is registered inline via the markup (e.g, <div id="relative" onclick="alert('foo');"></div>).
Why do you need to read the event handler? This is a relatively strange thing to do...
There are different ways of establishing event handlers, and they use different mechanisms inside the DOM. In particular — and as you've discovered empirically — adding an event listener via "addEventListener" does not affect the "onclick" attribute of the element. The mechanisms are simply separate.
This is one of the current limitation of W3C event registration model. if you register using JS methods then there is no standard way to get the handlers.
Latest DOM LEVEL 3 Events W3C adds eventListenerList spec. i guess we are lacking of some close support for this API across browsers.
Of-course if you add your method using tradition way
then your example would work.
Some StackOverFlow Links
link text

which HTML element lost focus?

in javascript, when I receive a focus event, how can I work out which element has lost focus? I'm trying to avoid having to put an onblur event handler on all elements within my web page.
#pbrodka: the target/srcElement property would refer to the element with focus for onfocus events
offhand I can't see a way to get this short of onblur, or if the set of objects you care about all have focus methods you could store a reference to that object instead. It's also possible event bubbling could get you out of jail
this all feels like a bit of a code smell though - perhaps you need to describe the problem in more detail
Difficult this. You cannot use event delegation to find out which control last produced a blur as focus/blur do not bubble up. There have been some attempts to 'fix' this but they are buggy and not resiliant cross browser.
Could I ask you why do you need this information as maybe there is an alternative solution.
Unfortunately, the onblur event doesn't bubble, otherwise you could have handled it at the window level to always know when an element lost focus.
As things are, I do believe it will be hard to do without, as you say, adding an onblur event handler to all elements (a truly nasty solution ;-).
It is possible to delegate the focus and blur events, if you follow PPK's advice, here:
http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html
The most simple solution is to write a function that walks all forms and then all elements within the form and installs an onblur handler for each (which will probably call some global function). This handler will get an event and this event will contain the info you seek.
This way, you just have to call this method once in body.onload and it will work no matter how complex your document is.
The only drawback is that you will need to call it if you dynamically add forms to your current document. In this case, you must make sure not to install the handler again (or you will get spurious duplicate events).

Categories