7

I have created a small imperative vanilla JavaScript script to block distracting news websites I feel an addiction-like behavior to:

// ==UserScript==
// @name         blocksite
// @match        *://*.news_site_1.com/*
// @match        *://*.news_site_2.com/*
// ==/UserScript==

function blocksite () {
    document.body.innerHTML =`<div dir="ltr"; style="font-size:100px; font-weight: bold; text-align: center">Blocked !</div>`;
}

setTimeout( blocksite(), 1000)
setTimeout( blocksite(), 5000) // Block possible later DOM mutations;
setTimeout( blocksite(), 10000) // Block possible later DOM mutations;

The script basically works (a popup takes over the DOM), but my problem is that it only blocks sites after all their DOM content was both parsed and rendered, while I am interested to block parsing generally.

While listening to load event is too late, listening to the earlier DOMContentLoaded event can have a better result than either listening to load or listening to setTimeout(), as blocking could occur right after content is parsed, instead of rendered.
Yet, I need a way to totally prevent the parsing of any webpage of the relevant websites (or alternatively, blocking any further parsing after the very first DOM HTML element node was parsed).

What I have tried

Per comments, I tried in Google Chrome:

window.stop(); I don't recall any significant change
window.close(); It worked for me only from devtool console
window.location.replace("about:blank"); It worked for me only after load event finished instead when parsing starts

My question

Does the operation I need even possible with the latest ECMAScript (10) and if so, what command should be used?


Update for Sxribe:

Dear Sxribe, I have created the following file with the following code.
The file does get loaded by Tampermonkey (With a proper @match list) but I saw no change in browser when loading matched websites (these websites aren't blocked and get loaded normally).

Code in file

<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
</head>
<body>

<h1>This is a Heading</h1>
<p>This is a paragraph.</p>

</body>
</html>

File call in Tampermonkey

window.open("C:\Users\MY_USER_NAME\Desktop\blocksite.html");
  • There's a Chrome extension [StayFocusd](https://chrome.google.com/webstore/detail/stayfocusd/laankejkbhbdhmipfmgcngdelahlfoji) that limits the amount of time you can spend on certain websites each day. – Barmar Nov 04 '19 at 21:15
  • @Barmar I know the concept of these extensions --- right now I happen to be using BlockSite), but I need an extensionless solution. –  Nov 04 '19 at 21:16
  • If you're running the script in the webpage itself, I don't think it can prevent parsing the webpage. – Barmar Nov 04 '19 at 21:19
  • @ShadowyShade you could do `window.location.href == "https://google.com"` or something – Sxribe Nov 04 '19 at 21:21
  • @Barmar indeed, on the webpage itself; I think that to run JavaScript in my Windows 10 machine would be only Node.js from WSL, or you mean something else? –  Nov 04 '19 at 21:21
  • @Sxribe very nice ! Thanks ! –  Nov 04 '19 at 21:22
  • This needs to run in the browser, not as a separate application. – Barmar Nov 04 '19 at 21:30
  • @Barmar regarding this particular code --- yes, I agree. I thought you might mean something else... Some other way to block the sites with Node.js maybe. –  Nov 04 '19 at 21:31

3 Answers3

4

To abort loading of a website, you can simply use the window.stop() method.

When called, when the current script finish running, the parsing of the website stops completely.

For example:

<p>Before scripts</p>
<script>
  document.write('<p>Before stop</p>')
  console.log('Before stop')

  window.stop()

  document.write('<p>After stop</p>')
  console.log('After stop')
</script>
<p>Between scripts</p>
<script>
  console.log('Second script')
  document.write('<p>Second script</p>')
</script>
<p>After scripts</p>

The above HTML displays:

Before scripts
Before stop

while you can see the following in the console:

Before stop
After stop

That shows that the <script> calling .stop() is fully evaluated, but changes made to DOM after .stop() aren't displayed.

Alternatively, to erase the full DOM content, it might be better to redirect the browser, that solution works even after page load:

window.open('about:blank','_self')
FZs
  • 16,581
  • 13
  • 41
  • 50
1

Old, wrong answer here: https://hastebin.com/vujuduforu.txt

Alright, so, chrome/firefox do not like having local files being opened with window.close(). In the end, I ended up simply hosting the website on glitch.com (free 100%), then redirecting to it. Here is my code for everything:

Tampermonkey Script:

// ==UserScript==
// @name         blocktest
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        *://*.bing.com/*
// ==/UserScript==

(function() {
    'use strict';
    window.open("https://block-sxribe.glitch.me/", "_self");
})();

HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>This site has been blocked.</title>
    <link rel="stylesheet" href="./index.css">
</head>
<body>
    <div class="flex-container">
        <div class="content">
            <h1>This site has been blocked.</h1>
            <p id="sep"></p>
            <p>This site was blocked with Tampermonkey.</p>
        </div>
    </div>
</body>
</html>

CSS:

@import url('https://fonts.googleapis.com/css?family=Open+Sans&display=swap');

* {
    margin: 0;
    padding: 0;
    font-family: 'Open Sans', sans-serif;
    text-transform: uppercase;
}

.flex-container {
    width: 100vw;
    height: 100vh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    text-align: center;
}

#sep {
    margin-left: 20vw;
    width: 60vw;
    border-bottom: 1px solid lightgray;
}

tl;dr Host website online, run window.open("website location.com", "_self") to open the website in current window.

Sxribe
  • 819
  • 7
  • 16
  • Hi, just one question, please --- why should loading the script from a custom-created file be faster from just writing the content in the script page of Tampermonkey? –  Nov 06 '19 at 22:25
  • It isn't a performance increase, but because it closes the previous window, new DOM content wont be loaded like you were having issues with. It's also cleaner code. Sorry for late reply – Sxribe Nov 09 '19 at 13:28
  • Well it might be the fastest way so far, not totally blocking but anyway very vast. –  Dec 06 '19 at 12:30
-1

If you are in any way in control of the website server, you could proxy the external scripts, or even internal scripts so that when you don't want then to be parsed, you just add return; at the top of each proxied script.

By proxying, I mean something like:

  1. You have a script, http://example.com/script.js
  2. You create a path within the application that loads http://example.com/script.js from the server and returns the result.
  3. If you don't want http://example.com/script.js to be parsed, either return an empty script or return the contents of http://example.com/script.js but after adding return; as the top of the file.

The path/route to proxy could be something like:

const script = encodeUriComponent('http://example.com/script.js')
http://myserver.com/proxy?url=script&allowed=false
McKabue
  • 2,076
  • 1
  • 19
  • 34