I've been playing around with the Google Polymer Shop demo and noticed that polymer systematically changes DOM event targets to the top-level component (in this case <shop-app>
).
document.addEventListener('click', function(event){
console.log('DOM click event target:',event.target);
});
As you can see, polymer systematically returns <shop-app>
as an event.target
even if you click different elements:
The problem with this behaviour is that it breaks all external JavaScript libraries which use event listeners to retrieve information about the original event target (all they see is <shop-app>
all the time).
As a workaround, I've been trying to retrieve the original event target (Polymer.dom(event).path[0]
) and dispatch a new event with it (https://pastebin.com/WKhGMrfx) but for some reason, my new event doesn't dispatch (I know I would end up with duplicate events, but my external libraries would work as at least some of those events would have the proper -
original - event target):
And my questions:
Q1: Is there a way to prevent polymer from overwriting event.target
?
Q2: Is there a way to dispatch events with the original event target?
in this code event is not real event, but it is a cloned object
function addEventListenerOverride(obj) {
if(obj._addEventListener){
obj.addEventListener = obj._addEventListener;
obj.removeEventListener = obj._removeEventListener;
}
obj._addEventListener = obj.addEventListener;
obj.addEventListener = function(a,b,c) {
if(c==undefined)
c=false;
this._addEventListener(a,b,c);
if(!this.eventListenerList)
this.eventListenerList = {};
if(!this.eventListenerList[a])
this.eventListenerList[a] = [];
//this.removeEventListener(a,b,c); // TODO - handle duplicates..
this.eventListenerList[a].push({listener:b,useCapture:c});
};
obj.getEventListeners = function(a){
if(!this.eventListenerList)
this.eventListenerList = {};
if(a==undefined)
return this.eventListenerList;
return this.eventListenerList[a];
};
obj.clearEventListeners = function(a){
if(!this.eventListenerList)
this.eventListenerList = {};
if(a==undefined){
for(var x in (this.getEventListeners()))
this.clearEventListeners(x);
return;
}
var el = this.getEventListeners(a);
if(el==undefined)
return;
for(var i = el.length - 1; i >= 0; --i) {
var ev = el[i];
this.removeEventListener(a, ev.listener, ev.useCapture);
}
};
obj._removeEventListener = obj.removeEventListener;
obj.removeEventListener = function(a,b,c) {
if(c==undefined)
c=false;
this._removeEventListener(a,b,c);
if(!this.eventListenerList)
this.eventListenerList = {};
if(!this.eventListenerList[a])
this.eventListenerList[a] = [];
// Find the event in the list
for(var i=0;i<this.eventListenerList[a].length;i++){
if(this.eventListenerList[a][i].listener==b, this.eventListenerList[a][i].useCapture==c){ // Hmm..
this.eventListenerList[a].splice(i, 1);
break;
}
}
if(this.eventListenerList[a].length==0)
delete this.eventListenerList[a];
};
}
//addEventListenerOverride(Element.prototype);
addEventListenerOverride(document);
//addEventListenerOverride(document.body);
function onDocumentClick(event){
if(event.isCustomized)
return
event.stopPropagation();
//event.preventDefault();
event.stopImmediatePropagation();
var normalizedEvent = Polymer.dom(event);
var eventClone = {};
for(var c in event){
eventClone[c] = event[c];
}
eventClone.target = normalizedEvent.rootTarget;
eventClone.isCustomized = true;
var eventType = event.type;
console.log("target should be: ", eventClone.target)
var listeners = document.getEventListeners(eventType);
if(listeners && listeners.length){
for(var i=0; i<listeners.length;i++){
listeners[i].listener(eventClone)
}
}
}
document.addEventListener('click', onDocumentClick);
document.addEventListener('click', function(event){
console.log('DOM click event:', event, 'target:', event.target);
});