如何防止 Google Polymer 改变 event.target?
How to prevent Google Polymer from changing event.target?
我一直在研究 Google Polymer Shop demo 并注意到聚合物系统地将 DOM 事件目标更改为顶级组件(在本例中为 <shop-app>
)。
- 转到https://shop.polymer-project.org/
- 打开控制台
- 粘贴下面的事件侦听器
document.addEventListener('click', function(event){
console.log('DOM click event target:',event.target);
});
- 单击演示并查看控制台日志
如您所见,聚合物系统地 returns <shop-app>
作为 event.target
即使您单击不同的元素:
此行为的问题在于它破坏了所有使用事件侦听器 来检索有关原始事件目标的信息的外部 JavaScript 库(它们只看到 <shop-app>
一直)。
作为一种解决方法,我一直在尝试检索原始事件目标 (Polymer.dom(event).path[0]
) 并使用它发送一个新事件 (https://pastebin.com/WKhGMrfx),但由于某种原因,我的新事件没有'dispatch(我知道我最终会得到重复的事件,但我的外部库会工作,因为至少其中一些事件会有适当的 -
原始 - 事件目标):
还有我的问题:
Q1:有没有办法防止聚合物覆盖event.target
?
Q2:有没有办法用原来的事件目标派发事件?
运行 此代码来自聚合物商店演示页面的控制台,然后检查点击事件的目标
function addEventListenerOverride(obj) {
if(obj._addEventListener)
return
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);
document.addEventListener('click', function(event){
if(event.isCustomized)
return
event.stopPropagation();
event.preventDefault();
event.stopImmediatePropagation();
//console.log('DOM click event 1:',event,'target:',event.target);
var normalizedEvent = Polymer.dom(event);
//event.oldTarget = event.target;
//event.target = normalizedEvent.rootTarget;
// logs #myButton
//console.info('rootTarget is:', normalizedEvent.rootTarget);
// logs the instance of event-targeting that hosts #myButton
//console.info('localTarget is:', normalizedEvent.localTarget);
// logs [#myButton, document-fragment, event-retargeting,
// body, html, document, Window]
//console.info('path is:', normalizedEvent.path);
var config = {};
for(var c in event){
config[c] = event[c];
}
config.bubbles = false;
var newTarget = normalizedEvent.rootTarget;
var eventType = event.type;
console.log("target should be: ", newTarget)
//config.target = normalizedEvent.rootTarget;
var fn = function(subEvent){
subEvent.preventDefault();
subEvent.stopImmediatePropagation();
//console.log("subEvent", subEvent.target)
//subEvent.type = "";
//console.log("subEvent", subEvent.type)
var listeners = document.getEventListeners(eventType);
if(listeners && listeners.length){
for(var i=0; i<listeners.length;i++){
var l = listeners[i].listener;
//l.call();
l(subEvent)
}
}
newTarget.removeEventListener(eventType, fn)
}
var oldEventListeners = (newTarget.getEventListeners(eventType) || []).concat([]);
console.log("oldEventListeners1", oldEventListeners)
newTarget.clearEventListeners(eventType);
newTarget.addEventListener(eventType, fn);
console.log("oldEventListeners2", oldEventListeners)
oldEventListeners.forEach(function(a){
newTarget.addEventListener(eventType, a.listener, a.useCapture);
})
var newEvent = new event.constructor(eventType, config);
newEvent.isCustomized = true;
//var shopAppEl = document.querySelector("shop-app");
//shopAppEl.fire(event.type, event.details, {node: newTarget})
setTimeout(function(){
try{
newTarget.dispatchEvent(newEvent);
}catch(e){
console.log("error", e)
}
},100)
});
document.addEventListener('click', function(event){
console.log('DOM click event:', event, 'target:', event.target);
});
这段代码中的事件不是真实事件,而是一个克隆对象
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);
});
我一直在研究 Google Polymer Shop demo 并注意到聚合物系统地将 DOM 事件目标更改为顶级组件(在本例中为 <shop-app>
)。
- 转到https://shop.polymer-project.org/
- 打开控制台
- 粘贴下面的事件侦听器
document.addEventListener('click', function(event){
console.log('DOM click event target:',event.target);
});
- 单击演示并查看控制台日志
如您所见,聚合物系统地 returns <shop-app>
作为 event.target
即使您单击不同的元素:
此行为的问题在于它破坏了所有使用事件侦听器 来检索有关原始事件目标的信息的外部 JavaScript 库(它们只看到 <shop-app>
一直)。
作为一种解决方法,我一直在尝试检索原始事件目标 (Polymer.dom(event).path[0]
) 并使用它发送一个新事件 (https://pastebin.com/WKhGMrfx),但由于某种原因,我的新事件没有'dispatch(我知道我最终会得到重复的事件,但我的外部库会工作,因为至少其中一些事件会有适当的 -
原始 - 事件目标):
还有我的问题:
Q1:有没有办法防止聚合物覆盖event.target
?
Q2:有没有办法用原来的事件目标派发事件?
运行 此代码来自聚合物商店演示页面的控制台,然后检查点击事件的目标
function addEventListenerOverride(obj) {
if(obj._addEventListener)
return
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);
document.addEventListener('click', function(event){
if(event.isCustomized)
return
event.stopPropagation();
event.preventDefault();
event.stopImmediatePropagation();
//console.log('DOM click event 1:',event,'target:',event.target);
var normalizedEvent = Polymer.dom(event);
//event.oldTarget = event.target;
//event.target = normalizedEvent.rootTarget;
// logs #myButton
//console.info('rootTarget is:', normalizedEvent.rootTarget);
// logs the instance of event-targeting that hosts #myButton
//console.info('localTarget is:', normalizedEvent.localTarget);
// logs [#myButton, document-fragment, event-retargeting,
// body, html, document, Window]
//console.info('path is:', normalizedEvent.path);
var config = {};
for(var c in event){
config[c] = event[c];
}
config.bubbles = false;
var newTarget = normalizedEvent.rootTarget;
var eventType = event.type;
console.log("target should be: ", newTarget)
//config.target = normalizedEvent.rootTarget;
var fn = function(subEvent){
subEvent.preventDefault();
subEvent.stopImmediatePropagation();
//console.log("subEvent", subEvent.target)
//subEvent.type = "";
//console.log("subEvent", subEvent.type)
var listeners = document.getEventListeners(eventType);
if(listeners && listeners.length){
for(var i=0; i<listeners.length;i++){
var l = listeners[i].listener;
//l.call();
l(subEvent)
}
}
newTarget.removeEventListener(eventType, fn)
}
var oldEventListeners = (newTarget.getEventListeners(eventType) || []).concat([]);
console.log("oldEventListeners1", oldEventListeners)
newTarget.clearEventListeners(eventType);
newTarget.addEventListener(eventType, fn);
console.log("oldEventListeners2", oldEventListeners)
oldEventListeners.forEach(function(a){
newTarget.addEventListener(eventType, a.listener, a.useCapture);
})
var newEvent = new event.constructor(eventType, config);
newEvent.isCustomized = true;
//var shopAppEl = document.querySelector("shop-app");
//shopAppEl.fire(event.type, event.details, {node: newTarget})
setTimeout(function(){
try{
newTarget.dispatchEvent(newEvent);
}catch(e){
console.log("error", e)
}
},100)
});
document.addEventListener('click', function(event){
console.log('DOM click event:', event, 'target:', event.target);
});
这段代码中的事件不是真实事件,而是一个克隆对象
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);
});