Prompt On New Tab

Display a confirmation dialog when the site wants to open a new tab, so that user has the chance to cancel or allow it to open in a new or current tab. This script won't work if the user opens a link in a new tab using web browser's "Open in a new tab", "Open in background tab", or similar which are web browser internal or browser extension features.

目前为 2019-11-07 提交的版本。查看 最新版本

// ==UserScript==
// @name         Prompt On New Tab
// @namespace    https://gf.qytechs.cn/en/users/85671-jcunews
// @version      1.2.18
// @license      GNU AGPLv3
// @description  Display a confirmation dialog when the site wants to open a new tab, so that user has the chance to cancel or allow it to open in a new or current tab. This script won't work if the user opens a link in a new tab using web browser's "Open in a new tab", "Open in background tab", or similar which are web browser internal or browser extension features.
// @author       jcunews
// @match        *://*/*
// @grant        none
// @run-at       document-start
// ==/UserScript==

((open_, submit_, wael, ele) => {

  //===== CONFIGURATION BEGIN =====

  /*
  Information about rejectList and allowList can be found on below URL.
  https://gf.qytechs.cn/en/scripts/38392-prompt-on-new-tab
  */

  var rejectList = [
    ["*", "*://*.doubleclick.net/*"],
    ["*", /^https?:\/\/[^.]+\.adservices?\.com\//i],
    ["*://site.com/*", /^.*?:\/\/site\.com\/(offer|popup)/i]
  ];

  var allowList = [
    ["*://www.bing.com/*", "*"],
    ["*://www.google.*/*", "*://*.google.*/*"]
  ];

  //If promptToOpenInCurrentTab is enabled, when the confirmation dialog is shown and the user chose Cancel,
  //an additional confirmation dialog will be shown to confirm whether the URL should be opened in current tab or not.
  var promptToOpenInCurrentTab = true;

  //===== CONFIGURATION END =====

  [rejectList, allowList].forEach(list => {
    list.forEach(pair => {
      pair.forEach((str, i) => {
        if (("string" === typeof str) || (str instanceof String)) {
          pair[i] = new RegExp("^" + str.replace(/([(){}\[\]\\^$.+?|])/g, "\\$1").replace(/([*])/g, ".*?") + "$", "i");
        }
      });
    });
  });

  function checkUrl(target, curUrl) {
    function checkUrlPair(pair) {
      return pair[0].test(curUrl) && pair[1].test(target);
    }

    curUrl = location.href;
    if (rejectList.some(checkUrlPair)) {
      return -1;
    } else if (allowList.some(checkUrlPair)) {
      return 1;
    } else return 0;
  }

  function getFrameNames(wnd, r, z) {
    r = ["_parent", "_self", "_top"];
    while (wnd) {
      try {
        Array.from(wnd.frames).forEach(f => {
          try {
            if (f.name) r.push(f.name);
          } catch(z) {}
        });
        if (wnd.parent === wnd) break;
        wnd = wnd.parent;
      } catch(z) {
        break;
      }
    }
    return r.length ? r : null;
  }

  function dummy(){}

  function isExistingFrameName(name) {
    return !name || (getFrameNames(window).indexOf(name) >= 0);
  }

  open_ = window.open;
  window.open = function(url, name) {
    var loc = {};
    if (isExistingFrameName(name)) {
      return open_.apply(this, arguments);
    } else switch (checkUrl(url)) {
      case 1:
        return open_.apply(this, arguments);
      case 0:
        if (confirm("This site wants to open a new tab.\nDo you want to allow it?\n\nURL:\n" + url)) {
          return open_.apply(this, arguments);
        } else if (promptToOpenInCurrentTab && confirm("URL:\n" + url + "\n\nDo you want to open it in current tab instead?")) {
          name = "_top";
          return open_.apply(this, arguments);
        }
    }
    return {
      document: {
        close: dummy,
        location: loc,
        open: dummy,
        write: dummy
      },
      location: loc
    };
  };

  function reject(ev) {
    if (!ev || !ev.preventDefault) return;
    ev.preventDefault();
    ev.stopPropagation();
    ev.stopImmediatePropagation();
  }

  function actionCheckUrl(ele, url, msg, ev) {
    switch (checkUrl(url)) {
      case 0:
        if (!confirm(msg + "\nDo you want to allow it?\n\nURL:\n" + url)) {
          if (promptToOpenInCurrentTab && confirm("URL:\n" + url + "\n\nDo you want to open it in current tab instead?")) {
            ele.target = "_top";
            break;
          }
          reject(ev);
          return false;
        } else break;
      case -1:
        reject(ev);
        return false;
    }
    return true;
  }

  function onFormSubmit(ev) {
    if ((/^https?:/).test(this.action) && !isExistingFrameName(this.target) &&
       !actionCheckUrl(this, this.action, "This site wants to submit a form in a new tab.")) return;
    return submit_.apply(this, arguments);
  }
  submit_ = HTMLFormElement.prototype.submit;
  HTMLFormElement.prototype.submit = onFormSubmit;

  function windowSubmit(ev){
    if (!ev.defaultPrevented && (/^https?:/).test(ev.target.action) && !isExistingFrameName(ev.target.target)) {
      return actionCheckUrl(ev.target, ev.target.action, "This site wants to submit a form in a new tab.", ev);
    }
  }
  addEventListener("submit", windowSubmit);

  function onAnchorClick(ev) {
    if ((/^(?:f|ht)tps?:/).test(this.href) && !isExistingFrameName(this.target)) {
      return actionCheckUrl(this, this.href, "This site wants to open a new tab.", ev);
    }
    return;
  }

  function windowClick(ev, a){
    if (ev.button || !(a = ev.target) || ev.defaultPrevented) return;
    if (a.tagName === "A") {
      return onAnchorClick.call(a, ev);
    } else while (a = a.parentNode) {
      if (a.tagName === "A") return onAnchorClick.call(a, ev);
    }
  }
  addEventListener("click", windowClick);

  wael = window.addEventListener;
  window.addEventListener = function(type, fn) {
    var res = wael.apply(this, arguments);
    if (type === "click") {
      removeEventListener("click", windowClick);
      wael("click", windowClick);
    } else if (type === "submit") {
      removeEventListener("click", windowSubmit);
      wael("submit", windowSubmit);
    }
    return res;
  };

})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址