Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ability to remove events #1

Closed
baptx opened this issue Jul 2, 2019 · 5 comments
Closed

ability to remove events #1

baptx opened this issue Jul 2, 2019 · 5 comments

Comments

@baptx
Copy link

baptx commented Jul 2, 2019

Hello,

Is there a way to remove events with the script getEventListeners.js? This would be useful as a Greasemonkey script that loads before the website content.

Some websites prevent copy-pasting or add other validation restrictions. So I reproduced a paste restriction by adding an event on a text input with Firefox:
document.getElementById("test").addEventListener("paste", function(e) {e.preventDefault()})

Then I tried to bypass this restriction by removing the event, based on this code that uses the default getEventListeners function of Chrome / Chromium (https://stackoverflow.com/questions/4386300/javascript-dom-how-to-remove-all-events-of-a-dom-object/40448083#40448083):
document.getElementById("test").getEventListeners().paste.forEach((e)=>{e.remove()})
But I get the error TypeError: e.remove is not a function.

I also tried a solution based on another code (https://stackoverflow.com/questions/4386300/javascript-dom-how-to-remove-all-events-of-a-dom-object/41877059#41877059):
document.removeEventListener("paste", document.getElementById("test").getEventListeners().paste[0].listener)
But it is still not possible to paste in the text input.

Thanks.

@colxi
Copy link
Owner

colxi commented Jul 2, 2019

No, it's not possible using getEventListeners....at least automatically.

However, because getEventListeners keeps track of all assigned event listeners, you can, ( after the page has been loaded, and the listeners have been assigned ), retrieve the list of listeners of an element, and remove it/them from the element using a conventional .removeEventListener( type, listener, useCapture)

In this example, the 'paste' event listener assigned to the element #myElement, should be removed...

// select the element
let el = document.querySelector( '#myElement' ); 
// retrieve the first "paste" event listener
let event = el.getEventListeners( 'paste' )[0];
// remove the listener
el.removeEventListener( event.type , event.listener, event.useCapture );

I hope it helps

@baptx
Copy link
Author

baptx commented Jul 3, 2019

Thanks! My second example was not working because I made a mistake by using document.removeEventListener instead of document.getElementById("test").removeEventListener.

Now it is fine like this also:
var el = document.getElementById("test"); el.removeEventListener("paste", el.getEventListeners().paste[0].listener)

Your example works too but you have to remove the "#" for the getElementById function.
Is it better to use getEventListeners().paste[0] instead of getEventListeners("paste")[0] or it is the same except that we can pass variables in the second example? I guess .paste can be a bit faster in some case since it is directly available as an attribute.
By the way, did you write this getEventListeners function yourself or you took it from a Chromium / Chrome or Firebug implementation?

@colxi
Copy link
Owner

colxi commented Jul 3, 2019

Both getEventListeners().paste[0] and of getEventListeners("paste")[0] are exactly tyhe same. Same results, and same performance.

This is my own getEventListeners implementation, no code from Chromium or Firebug code has been used at all.

@colxi colxi closed this as completed Jul 3, 2019
@angstyloop
Copy link

angstyloop commented Nov 2, 2022

I like this tool a lot, but it bothers me on a personal level that the JS Web API doesn't do listener management for you. Everyone who programs with JS should be exposed to this approach, even if they already have an awesome tool that owns. Thanks colxi for the great tool.

An alternative solution to listener management in JS is to extend the EventTarget class from the JS Web API, overriding the addEventListener and removeEventListener methods to maintain a data structure containing the listener function references.

I follow this approach in the Gist below, where I also have a few unit tests. You can run the tests in the browser JS console by copying the code from the Gist to your clipboard, pasting it into the browser JS console, and pressing enter. Please read strange JS from the internet before running it in your JS browser console.

https://gist.github.com/angstyloop/504414aba95b61b98be0db580cb2a3b0

@baptx
Copy link
Author

baptx commented Nov 18, 2022

@angstyloop What is the difference / advantage with your script?

@colxi For information, I was able to use successfully your script with Greasemonkey to bypass a paste event restriction on a website, very useful. Basically I used the Content Script Injection method from Greasemonkey (https://wiki.greasespot.net/Content_Script_Injection) to inject the getEventListeners function on page load by creating a Greasemonkey script with the code window.eval(...); where ... is the code of getEventListeners.js between the backticks to support multiline.
Then I executed the JavaScript code from my previous comment in the web console to remove the paste event.
It could also probably be done with a tool like mitmproxy to inject the code in existing JavaScript files if there are CSP restrictions forbidding inline JavaScript (or we could get rid of CSP if we don't care about this protection, by editing HTTP headers with an addon like https://github.com/FirefoxBar/HeaderEditor).
Using a tool like https://github.com/kyoto/sendkeys could also bypass paste restrictions but it requires an external software, like it is the case with mitmproxy.
Setting the value through JavaScript like document.getElementById("test").value = "XXX"; could also be a solution (https://stackoverflow.com/questions/4386300/javascript-dom-how-to-remove-all-event-listeners-of-a-dom-object/56849582#56849582).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants