如何防止浏览器在vanilla JavaScript中加载Web应用程序?

时间:2018-03-10 11:02:04

标签: javascript browser google-chrome-extension greasemonkey tampermonkey

我写了下面的Greasemonkey脚本,以防止自己访问一些网络应用程序(网站),通常这些我觉得有点上瘾。这是我最接近阻止我的浏览器显示这些网站的地方:

// ==UserScript==
// @name        blocko
// @include     *
// ==/UserScript==

window.addEventListener('load', function() {
    let sites = ['example-1.com', 'example-2.com', 'example-3.com'];
    let dotTLD_andAllAfterIt = /\..+/;
    let href = window.location.href;
    for (let i = 0; i < sites.length; i++) {
        if (href.includes(sites[i])) {
            let domain = sites[i].replace(dotTLD_andAllAfterIt, '');
            document.body.innerHTML =`
                <div style="direction: ltr; position: fixed; top: 0; z-index: 999999; display: block; width: 100%; height: 100%; background: red">
                  <p style="position: relative; top: 40%; display: block; font-size: 66px; font-weight: bold; color: #fff; margin: 0 auto; text-align: center">
                    Enough with this ${domain} bullshit!
                  </p>
                </div>
          `;
        }
    }
}, true);

我不满意我的成就,因为这个剧本让我进入网站,我需要等待1/2/3/4甚至5秒或更长时间的极少数情况,直到该网站将消失并且我将以红色背景打印到屏幕上的消息将显示。因此,我不情愿地接触到我想避免的网站内容。

我希望阻止浏览器通过JavaScript导航到网站。有一个名为&#34; BlockSite&#34;的Chrome插件。这有助于解决这个问题,我试图检查它的(巨大的)源代码,但却无法理解它如何阻止用户移动到网站,这与上面的脚本不同,后者将用户移动到网站但几秒钟后(在load事件被触发后)消息网站上显示一条消息。

请分享一种完全阻止自己进入网站的方法,例如&#34; BlockSite&#34;。

4 个答案:

答案 0 :(得分:5)

作为解决方案,您可以覆盖网站中所有链接的onclick方法。 然后决定让用户关注链接。

const blackList = [`example-1.com`, `example-2.com`]

function onClick(event) {
  const href = this.href.match(/^(?:https?:)?(?:\/\/)?(?:[^@\n]+@)?(?:www\.)?([^:\/\n]+)/i)
  if (!href) return
  const domain = href[1]
  if (blackList.includes(domain)) {
    event.stopPropagation()
    event.preventDefault()
    document.body.innerHTML =`
      <p>
        Enough with this ${domain} bullshit!
      </p>
    `;
  }
}

const elements = document.getElementsByTagName(`a`);
for(let element of elements) {
  element.onclick = onClick
}

:更新:。

好的,让我解释一下上面的代码。

代码会将click侦听器添加到当前页面的所有链接(<a href="...">...</a>)。当用户点击上面的功能时会触发。

const href = this.href.match - 我们从href中提取唯一的域部分,以便比较我们的blackList中是否存在url - &gt; if (blackList.includes(domain))

this - 请参阅链接属性href以获取更多信息,请查看此article

以下是demo,此处为source code

答案 1 :(得分:5)

只要您使用public abstract class Table<E extends Element> extends ArrayList<E> { public Table<E> map(Function<E, E> mapper) { return this.stream().map(mapper).collect(TableImpl::new, TableImpl::add, TableImpl::addAll); } public Table<E> filter(Predicate<E> predicate) { return this.stream().filter(predicate).collect(TableImpl::new, TableImpl::add, TableImpl::addAll); } } class TableImpl extends Table { //whatever you impl is } 事件,就需要等待。您需要使用Collector事件。区别在于here on this answer

如果你改变

,它会更快
window load

DOMContentLoaded

有许多免费扩展程序可用于阻止不受欢迎的域名。如果您想为Chrome构建一个,请告诉我,在这种情况下,我可以进一步协助。

更新:根据评论

删除了以下段落

但是如果你想自己进行扩展,那么你需要特定于浏览器。因为您需要为不同的浏览器编写不同的扩展名。

答案 2 :(得分:1)

阻止网站在浏览器中显示的最佳方法是使用CSS加载之前。这样的事情应该做得很好:

/* hide all child elements of <body> */
body > * {
  display: none !important;
}
/* just in case, hide text directly inside <body> too */
body {
  color: transparent !important;
  font-size: 0px !important;
}
/* inject an overlay to show a message and to cover up anything that might
   still somehow be visible after the styles above */
body::before {
  content: 'Enough with this BS!';
  display: block;
  width: 100%;
  height: 100%;
  position: fixed;
  z-index: 999999;
  text-align: center;
  font-size: 36pt;
  font-family: sans-serif;
  color: red;
  background: black;
}

使用类似于Stylish的user style扩展名,您可以将上面的CSS设置为您要阻止的所有域的用户样式。该扩展程序会在加载之前将用户样式注入页面,从而完全防止页面上的任何内容甚至短暂可见。

或者,您也可以通过将样式包装在用户脚本中并自己将其注入页面来实现类似的结果。您可以使用@run-at document-start header指令尽可能早地运行用户脚本,甚至在页面加载之前,再次将实际页面内容显示的风险降至最低:

// ==UserScript==
// @name        Enough with this BS
// @version     0.1
// @description Block any sites this script runs on with a rude message.
// @author      Ilmari Karonen
// @match       *://*.example.com/*
// @grant       none
// @run-at      document-start
// ==/UserScript==

var style = `
    /* hide all child elements of <body> */
    body > * {
      display: none !important;
    }
    /* just in case, hide text directly inside <body> too */
    body {
      color: transparent !important;
      font-size: 0px !important;
    }
    /* inject an overlay to show a message and to cover up anything that might
       still somehow be visible after the styles above */
    body::before {
      content: 'Enough with this ${location.hostname} BS!';
      display: block;
      width: 100%;
      height: 100%;
      position: fixed;
      z-index: 999999;
      text-align: center;
      font-size: 36pt;
      font-family: sans-serif;
      color: red;
      background: black;
    }`;

// Inject style into page
var styleElem = document.createElement( 'style' );
styleElem.type = 'text/css';
styleElem.textContent = style;
( document.head || document.documentElement ).appendChild( styleElem );

这种方法的一个优点是您可以使用JS来自定义每个站点的样式,例如在上面的消息中包含网站名称。

请注意,上面的脚本不包含任何用于匹配要阻止的网站的正则表达式;相反,它在用户脚本标头中使用@match expressions来告诉用户脚本管理器仅在某些站点上运行它。 (上面的示例标题只会阻止example.com及其任何子域的所有内容。)

这样做的一个优点是regexp匹配更有效,因为脚本不会在任何其他页面上运行;另一个是大多数用户脚本管理器提供用于添加额外匹配和/或排除模式的UI,而无需直接编辑脚本。

(另外可能值得注意的是,我使用ES2015 template literal在JS代码中嵌入了样式表,因为旧式JS字符串不能跨越多行。在SO上突出显示的代码似乎不太要正确理解这种语法,这就是为什么它看起来有点滑稽。)

答案 3 :(得分:1)

  • 如果要停止,请尝试此操作:window.stop documentation(无法停止加载时包含该文档的文档)
  • 试试这个 你想阻止网页重新加载/重定向链接:onbeforeunload documentation(不要自动阻止加载,但允许用户选择是否跟踪链接)

    window.onbeforeunload = function(e) {
    
      var dialogText = 'Are you sure?';
    
       e.returnValue = dialogText;
    
       return dialogText;
    
    };