Browse Source

feat: use GM.openInTab and add background param

Sv443 1 year ago
parent
commit
fa09004288
3 changed files with 36 additions and 24 deletions
  1. 6 0
      .changeset/wet-bikes-scream.md
  2. 7 6
      README.md
  3. 23 18
      lib/dom.ts

+ 6 - 0
.changeset/wet-bikes-scream.md

@@ -0,0 +1,6 @@
+---
+"@sv443-network/userutils": minor
+---
+
+Made `openInNewTab()` use `GM.openInTab` by default and fall back to the old behavior.  
+Also added `background` param to specify if the tab should get focus when opened.

+ 7 - 6
README.md

@@ -582,14 +582,14 @@ preloadImages([
 ### openInNewTab()
 Usage:  
 ```ts
-openInNewTab(url: string): void
+openInNewTab(url: string, background?: boolean): void
 ```
   
-Creates an invisible anchor with a `_blank` target and clicks it.  
-Contrary to `window.open()`, this has a lesser chance to get blocked by the browser's popup blocker and doesn't open the URL as a new window.  
-This function has to be run in response to a user interaction event, else the browser might reject it.  
+Tries to use `GM.openInTab` to open the given URL in a new tab, or as a fallback if the grant is not given, creates an invisible anchor element and clicks it.  
+If `background` is set to true, the tab will be opened in the background. Leave `undefined` to use the browser's default behavior.  
   
-⚠️ This function needs to be run after the DOM has loaded (when using `@run-at document-end` or after `DOMContentLoaded` has fired).  
+⚠️ Needs the `@grant GM.openInTab` directive, otherwise only the fallback behavior will be used and the warning below is extra important:  
+⚠️ For the fallback to work, this function needs to be run in response to a user interaction event, else the browser might reject it.  
   
 <details><summary><b>Example - click to view</b></summary>
 
@@ -597,7 +597,8 @@ This function has to be run in response to a user interaction event, else the br
 import { openInNewTab } from "@sv443-network/userutils";
 
 document.querySelector("#my-button").addEventListener("click", () => {
-  openInNewTab("https://example.org/");
+  // open in background:
+  openInNewTab("https://example.org/", true);
 });
 ```
 

+ 23 - 18
lib/dom.ts

@@ -66,25 +66,30 @@ export function preloadImages(srcUrls: string[], rejects = false) {
 }
 
 /**
- * Creates an invisible anchor with a `_blank` target and clicks it.  
- * Contrary to `window.open()`, this has a lesser chance to get blocked by the browser's popup blocker and doesn't open the URL as a new window.  
- *   
- * This function has to be run in response to a user interaction event, else the browser might reject it.
+ * Tries to use `GM.openInTab` to open the given URL in a new tab, otherwise if the grant is not given, creates an invisible anchor element and clicks it.  
+ * For the fallback to work, this function needs to be run in response to a user interaction event, else the browser might reject it.
+ * @param href The URL to open in a new tab
+ * @param background If set to `true`, the tab will be opened in the background - set to `undefined` (default) to use the browser's default behavior
  */
-export function openInNewTab(href: string) {
-  const openElem = document.createElement("a");
-  Object.assign(openElem, {
-    className: "userutils-open-in-new-tab",
-    target: "_blank",
-    rel: "noopener noreferrer",
-    href,
-  });
-  openElem.style.display = "none";
-
-  document.body.appendChild(openElem);
-  openElem.click();
-  // timeout just to be safe
-  setTimeout(openElem.remove, 50);
+export function openInNewTab(href: string, background?: boolean) {
+  try {
+    GM.openInTab(href, background);
+  }
+  catch(e) {
+    const openElem = document.createElement("a");
+    Object.assign(openElem, {
+      className: "userutils-open-in-new-tab",
+      target: "_blank",
+      rel: "noopener noreferrer",
+      href,
+    });
+    openElem.style.display = "none";
+
+    document.body.appendChild(openElem);
+    openElem.click();
+    // timeout just to be safe
+    setTimeout(openElem.remove, 50);
+  }
 }
 
 /**