首页 文章

如何防止Google Polymer更改event.target?

提问于
浏览
0

我一直在玩Google Polymer Shop demo,并注意到聚合物系统地将DOM事件目标更改为顶级组件(在本例中为 <shop-app> ) .

document.addEventListener('click', function(event){ console.log('DOM click event target:',event.target); });

  • 点击演示并查看控制台日志

如您所见,即使您单击不同的元素,聚合物也会系统地返回 <shop-app>event.target

enter image description here

The problem with this behaviour is that it breaks all external JavaScript libraries which use event listeners 检索有关原始事件目标的信息(他们所看到的只是 <shop-app> ) .

作为一种解决方法,我一直在尝试检索原始事件目标( Polymer.dom(event).path[0] )并用它调度一个新事件(https://pastebin.com/WKhGMrfx)但由于某种原因,我的新事件没有发送(我知道我最终会重复事件,但我的外部库将起作用,因为至少其中一些事件将具有正确的 - 原始 - 事件目标):

enter image description here

我的问题是:

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?

2 回答

  • 1

    在此代码事件中不是真实事件,但它是一个克隆对象

    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);
    });
    
  • 1

    从聚合物商店演示页面的控制台运行此代码,然后检查点击事件的目标

    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);
    });
    

相关问题