Переглянути джерело

feat: add argument `additionalProps` to `openInNewTab()`

Sv443 3 місяців тому
батько
коміт
cd241b0
3 змінених файлів з 22 додано та 8 видалено
  1. 5 0
      .changeset/great-donuts-roll.md
  2. 4 3
      docs.md
  3. 13 5
      lib/dom.ts

+ 5 - 0
.changeset/great-donuts-roll.md

@@ -0,0 +1,5 @@
+---
+"@sv443-network/userutils": minor
+---
+
+Added `additionalProps` parameter to `openInNewTab()` to add or overwrite anchor element props (only if `GM.openInTab()` is unavailable)

+ 4 - 3
docs.md

@@ -528,11 +528,12 @@ preloadImages([
 ### openInNewTab()
 Signature:  
 ```ts
-openInNewTab(url: string, background?: boolean): void
+openInNewTab(url: string, background?: boolean, additionalProps?: Partial<HTMLAnchorElement>): void
 ```
   
 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.  
+If `additionalProps` is set and `GM.openInTab` is not available, the given properties will be added or overwritten on the created anchor element.  
   
 ⚠️ 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.  
@@ -954,8 +955,8 @@ digitCount(num: number | Stringifiable): number
 ```
   
 Calculates and returns the amount of digits in the given number.  
-The given value will be converted by being passed to `String()` and then `Number()` before the calculation.  
-Returns `NaN` if the number is invalid.  
+If it isn't a number already, the value will be converted by being passed to `String()` and then `Number()` before the calculation.  
+Returns `NaN` if the number is invalid and `Infinity` if the number is too large to be represented as a regular number.
   
 <details><summary><b>Example - click to view</b></summary>
 

+ 13 - 5
lib/dom.ts

@@ -61,10 +61,11 @@ export function preloadImages(srcUrls: string[], rejects = false): Promise<Promi
  * 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
+ * @param additionalProps Additional properties to set on the anchor element (only applies when `GM.openInTab` is not available)
  */
-export function openInNewTab(href: string, background?: boolean) {
+export function openInNewTab(href: string, background?: boolean, additionalProps?: Partial<HTMLAnchorElement>): void {
   try {
-    GM.openInTab(href, background);
+    GM.openInTab?.(href, background);
   }
   catch(e) {
     const openElem = document.createElement("a");
@@ -72,14 +73,21 @@ export function openInNewTab(href: string, background?: boolean) {
       className: "userutils-open-in-new-tab",
       target: "_blank",
       rel: "noopener noreferrer",
+      tabIndex: -1,
+      ariaHidden: "true",
       href,
+      ...additionalProps,
+    });
+    Object.assign(openElem.style, {
+      display: "none",
+      pointerEvents: "none",
     });
-    openElem.style.display = "none";
 
     document.body.appendChild(openElem);
     openElem.click();
-    // timeout just to be safe
-    setTimeout(openElem.remove, 50);
+
+    // schedule removal after the click event has been processed
+    setTimeout(openElem.remove, 0);
   }
 }