code

Javascript / DOM : DOM 개체의 모든 이벤트를 제거하는 방법은 무엇입니까?

codestyles 2020. 11. 1. 18:08
반응형

Javascript / DOM : DOM 개체의 모든 이벤트를 제거하는 방법은 무엇입니까?


질문 : div와 같은 객체의 모든 이벤트를 완전히 제거 할 수있는 방법이 있습니까?

편집 : div.addEventListener('click',eventReturner(),false);이벤트 별로 추가 하고 있습니다.

function eventReturner() {
    return function() {
        dosomething();
    };
}

EDIT2 : 작동하지만 내 경우에 사용할 수없는 방법을 찾았습니다.

var returnedFunction;
function addit() {
    var div = document.getElementById('div');
    returnedFunction = eventReturner();
    div.addEventListener('click',returnedFunction,false); //You HAVE to take here a var and not the direct call to eventReturner(), because the function address must be the same, and it would change, if the function was called again.
}
function removeit() {
    var div = document.getElementById('div');
    div.removeEventListener('click',returnedFunction,false);
}

모든 이벤트 제거가 무슨 뜻인지 잘 모르겠습니다 . 특정 유형의 이벤트에 대한 모든 처리기를 제거하거나 한 유형에 대한 모든 이벤트 처리기를 제거 하시겠습니까?

모든 이벤트 핸들러 제거

모든 이벤트 핸들러 (모든 유형)를 제거 하려면 요소를 복제 하고 복제로 바꿀 수 있습니다.

var clone = element.cloneNode(true);

참고 : 이렇게하면 속성과 자식이 유지되지만 DOM 속성에 대한 변경 사항은 유지되지 않습니다.


특정 유형의 "익명"이벤트 핸들러 제거

다른 방법은 사용하는 removeEventListener()것이지만 이미 시도했지만 작동하지 않은 것 같습니다. 여기에 캐치가 있습니다 .

addEventListener익명 함수를 호출 하면 매번 새 리스너가 생성됩니다. removeEventListener익명 함수를 호출해도 효과가 없습니다 . 익명 함수는 호출 될 때마다 고유 한 객체를 생성하지만 기존 객체에 대한 참조는 아니지만 호출 할 수 있습니다. 이러한 방식으로 이벤트 리스너를 추가 할 때는 한 번만 추가해야합니다. 추가 된 객체가 제거 될 때까지 영구적 (제거 할 수 없음)입니다.

기본적으로 익명 함수를 addEventListener전달하여 함수를 eventReturner반환합니다.

이 문제를 해결할 수있는 두 가지 가능성이 있습니다.

  1. 함수를 반환하는 함수를 사용하지 마십시오. 함수를 직접 사용하십시오.

    function handler() {
        dosomething();
    }
    
    div.addEventListener('click',handler,false);
    
  2. addEventListener반환 된 함수에 대한 참조를 저장 하는 래퍼를 만들고 이상한 removeAllEvents함수를 만듭니다 .

    var _eventHandlers = {}; // somewhere global
    
    function addListener(node, event, handler, capture) {
        if(!(node in _eventHandlers)) {
            // _eventHandlers stores references to nodes
            _eventHandlers[node] = {};
        }
        if(!(event in _eventHandlers[node])) {
            // each entry contains another entry for each event type
            _eventHandlers[node][event] = [];
        }
        // capture reference
        _eventHandlers[node][event].push([handler, capture]);
        node.addEventListener(event, handler, capture);
     }
    
    function removeAllListeners(node, event) {
        if(node in _eventHandlers) {
            var handlers = _eventHandlers[node];
            if(event in handlers) {
                var eventHandlers = handlers[event];
                for(var i = eventHandlers.length; i--;) {
                    var handler = eventHandlers[i];
                    node.removeEventListener(event, handler[0], handler[1]);
                }
            }
        }
    }
    

    그리고 다음과 함께 사용할 수 있습니다.

    addListener(div, 'click', eventReturner(), false)
    // and later
    removeListeners(div, 'click')
    

데모

참고 : 코드가 오랫동안 실행되고 많은 요소를 만들고 제거하는 _eventHandlers경우 제거 할 때 포함 된 요소를 제거해야 합니다.


이벤트 리스너의 자체 기능을 사용합니다 remove(). 예를 들면 :

getEventListeners().click.forEach((e)=>{e.remove()})

이렇게하면 자식에서 모든 리스너가 제거되지만 큰 페이지의 경우 속도가 느려집니다. 작성하기 매우 간단합니다.

element.outerHTML = element.outerHTML;

corwin.amber가 말했듯이 Webkit과 다른 웹킷 사이에는 차이점이 있습니다.

Chrome에서 :

getEventListeners(document);

기존의 모든 이벤트 리스너가있는 객체를 제공합니다.

Object 
 click: Array[1]
 closePopups: Array[1]
 keyup: Array[1]
 mouseout: Array[1]
 mouseover: Array[1]
 ...

여기에서 제거하려는 리스너에 도달 할 수 있습니다.

getEventListeners(document).copy[0].remove();

따라서 모든 이벤트 리스너 :

for(var eventType in getEventListeners(document)) {
   getEventListeners(document)[eventType].forEach(
      function(o) { o.remove(); }
   ) 
}

Firefox에서

Is a little bit different because it uses a listener wrapper that contains no remove function. You have to get the listener you want to remove:

document.removeEventListener("copy", getEventListeners(document).copy[0].listener)

All the event listeners:

for(var eventType in getEventListeners(document)) {
  getEventListeners(document)[eventType].forEach(
    function(o) { document.removeEventListener(eventType, o.listener) }
  ) 
}

I stumbled with this post trying to disable the annoying copy protection of a news website.

Enjoy!


May be the browser will do it for you if you do something like:

Copy the div and its attributes and insert it before the old one, then move the content from the old to the new and delete the old?


Chrome only

As I'm trying to remove an EventListener within a Protractor test and do not have access to the Listener in the test, the following works to remove all event listeners of a single type:

function(eventType){
    getEventListeners(window).[eventType].forEach(
        function(e){
            window.removeEventListener(eventType, e.listener)
        }
    );
}

I hope this helps someone as previous answer were using the "remove" method which since then does not work anymore.


To complete the answers, here are real-world examples of removing events when you are visiting websites and don't have control over the HTML and JavaScript code generated.

Some annoying websites are preventing you to copy-paste usernames on login forms, which could easily be bypassed if the onpaste event was added with the onpaste="return false" HTML attribute. In this case we just need to right click on the input field, select "Inspect element" in a browser like Firefox and remove the HTML attribute.

However, if the event was added through JavaScript like this:

document.getElementById("lyca_login_mobile_no").onpaste = function(){return false};

We will have to remove the event through JavaScript also:

document.getElementById("lyca_login_mobile_no").onpaste = null;

In my example, I used the ID "lyca_login_mobile_no" since it was the text input ID used by the website I was visiting.

Another way to remove the event (which will also remove all the events) is to remove the node and create a new one, like we have to do if addEventListener was used to add events using an anonymous function that we cannot remove with removeEventListener. This can also be done through the browser console by inspecting an element, copying the HTML code, removing the HTML code and then pasting the HTML code at the same place.

It can also be done faster and automated through JavaScript:

var oldNode = document.getElementById("lyca_login_mobile_no");
var newNode = oldNode.cloneNode(true);
oldNode.parentNode.insertBefore(newNode, oldNode);
oldNode.parentNode.removeChild(oldNode);

Update: if the web app is made using a JavaScript framework like Angular, it looks the previous solutions are not working or breaking the app. Another workaround to allow pasting would be to set the value through JavaScript:

document.getElementById("lyca_login_mobile_no").value = "username";

At the moment, I don't know if there is a way to remove all form validation and restriction events without breaking an app written entirely in JavaScript like Angular.


You could add another event listener and call preventDefault() to stop propagation of the previous listeners.

document.querySelectorAll('a.my-link').forEach((el) => {
  el.addEventListener('click', (ev) => {
    ev.preventDefault()
  })
})

One method is to add a new event listener that calls e.stopImmediatePropagation().


var div = getElementsByTagName('div')[0]; /* first div found; you can use getElementById for more specific element */
div.onclick = null; // OR:
div.onclick = function(){};

//edit

I didn't knew what method are you using for attaching events. For addEventListener you can use this:

div.removeEventListener('click',functionName,false); // functionName is the name of your callback function

more details


Removing all the events on document:

One liner:

for (key in getEventListeners(document)) { getEventListeners(document)[key].forEach(function(c) { c.remove() }) }

Pretty version:

for (key in getEventListeners(document)) {
  getEventListeners(document)[key].forEach(function(c) {
    c.remove()
  })   
}

참고URL : https://stackoverflow.com/questions/4386300/javascript-dom-how-to-remove-all-events-of-a-dom-object

반응형