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

Rewrite of enable-text-selection.js and add text-selection-demo.html #5

Merged
merged 3 commits into from Jun 27, 2016

Conversation

Projects
None yet
2 participants
@RoxKilly
Copy link
Contributor

RoxKilly commented Jun 11, 2016

Alan, thanks for the invite to submit a pull request. I rewrote enable-text-selection.js to get rid of jQuery depedency and generally improve its countermeasures. I also wrote text-selection-demo.html, to test our countermeasures to most commonly used text-selection blocks.

Limitations of the previous version that I've attempted to address with my rewrite:

  1. It downloaded the whole JQuery package (unless the browser had already gotten it for the site's own scripts), a 90+ KB dependency for a tiny script.

  2. It failed to disable Javascript based blocks if jQuery was not allowed to load. Users of extensions that limit 3rd party connections were affected. For instance, uBlock Origin or NoScript which prevent sites from connecting to 3rd parties to download scripts (for security) would also neuter this script.

  3. It entered an infinite loop if jQuery loading failed. One would notice 'allowTextSelectionWhenPossible' and 'jQuery still not loaded.' printed to the console several times a second, forever.

  4. In certain cases, it would fail to properly defeat measures put in place without the use of jQuery, even if jQuery subsequently loaded properly. This can be tested by trying to apply the previous script to text-selection-demo.html. This limitation is due to the fact that it relies on jQuery's "unbind" function, but since "unbind" isn't given a reference to the initial event listener (we have no way to know it), it will only work if the original event was registered with jQuery (since jQuery keeps a map of all the listeners it has registered so it can refer to them later when unbind is used without the needed reference). This effectively limited the script's usefulness on sites that did not already use jQuery.

  5. It did not address disabled text inputs, an easy and effective way to prevent text selection and copying.

Note: This is my first attempt at pushing and generating a pull request. Let me know if I break any rule or convention

RoxKilly added some commits Jun 10, 2016

Webpage demonstrating techniques used to prevent text selection. Can …
…be used to demo or test countermeasures to such limitations.
Rewrote script at Alan Hogan's invitation to address my concerns: Lim…
…itations of the previous version that I've attempted to address with my rewrite:

1) It downloads the whole JQuery package (unless the browser has already gotten it for the site's own scripts), a 90+ KB dependency for a tiny script.

2) It failed to disable Javascript based blocks if JQuery was not allowed to load. Users of extensions that limit 3rd party connections were affected. For instance, uBlock Origin or NoScript which prevent sites from connecting to 3rd parties to download scripts (for security).

3) It entered an infinite loop if JQuery loading continued to fail. One would notice 'allowTextSelectionWhenPossible' and 'jQuery still not loaded.' printed to the console several times a second forever.

4) In certain cases, it would fail to properly defeat measures put in place without the use of jQuery, even if jQuery subsequently loaded properly. This can be tested by trying to apply the previous script to text-selection-demo.html.  This limitation is due to the fact that it relies on  jQuery's "unbind" function, but since "unbind" isn't given a reference to the initial event listener (we have no way to know it), it will only work if the original event was registered with jQuery (since jQuery keeps a map of all the listeners it has registered so it can refer to them later). This effectively limited the script's usefulness on sites that did not already use jQuery.

5) It did not address disabled text inputs, an easy and effective way to prevent text selection and copying.

//Put all of <body> children in a collection
//Use getElementsByTagName because it has better compatibility (it's older) than querySelectorAll('*')
var elArray = document.body.getElementsByTagName('*');

This comment has been minimized.

@alanhogan

alanhogan Jun 27, 2016

Owner

Huh. Haven't seen this trick before! Surprised that works. Neat trick

el.onselectstart = el.ondragstart = el.ondrag = el.oncontextmenu = el.onmousedown
= el.onmouseup = function(){return true};

if(el instanceof HTMLInputElement && el.type == 'text'){

This comment has been minimized.

@alanhogan

alanhogan Jun 27, 2016

Owner

I wonder if there is a way to detect not just type=text but all text-like inputs, e.g., <input type="email">

@alanhogan

This comment has been minimized.

Copy link
Owner

alanhogan commented Jun 27, 2016

Hey @RoxKilly, my apologies for having missed this PR at first. I haven't been super on top of my personal email inbox.

I really appreciate a lot about this pull request:

  • The lengthy description here
  • The added strategy comments in the source
  • The added test page

etc.

I left a comment regarding a potential improvement — I’m not sure if it’s straightforwardly possible, though — but I’m happy to merge this now and release it to better help users of the bookmarklet.

Thanks so much.

@alanhogan alanhogan merged commit 0e1d677 into alanhogan:master Jun 27, 2016

@RoxKilly

This comment has been minimized.

Copy link
Contributor

RoxKilly commented Jun 27, 2016

I did it; my first contribution to any repo anywhere :-)

Thanks for the suggestion. Implemented it at #6

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment