Keyboard Event:在網頁上自定義快速鍵

先前寫了一堆 userscript 針對不同的網站加上快速鍵 (像是翻下一頁或是上一頁):

然後發現太多重複的事情了,就寫成 Chrome 的 extension 了:「Keyboard Event」,程式碼在 GitHub 上有放:「gslin/keyboard-event」,不信任一致性的話也可以用 Chrome extension source viewer 直接看 chrome web store 上面放的版本。

這個 extension 的想法是設定 hostname、path 以及按鍵,接著設定按鍵按下後會觸發的 DOM element (用 CSS selector 選) 與 DOM event (像是 mouseover 這樣的 event 字串)。

而其中 click event 常常不會動 (對應實際的呼叫是 element.dispatchEvent(new Event('click'))),在 debug 時發現需要用 click() (對應實際的呼叫是 element.click()),所以有特別接受 click() 這個字串。

這個舉個例子,我有一組設定是:

www.instagram.com
.*
<
div[role="dialog"] button[aria-label="Go back"]
click()

www.instagram.com
.*
>
div[role="dialog"] button[aria-label="Next"]
click()

在瀏覽器上面看 Instagram 的照片時可以用 <> 快速切換照片。

另外設定的部分支援 chrome.storage 的 browser sync,對於有多瀏覽器時會自動同步設定檔,不用每一台都設定一次...

這算是第一次寫 Manifest V3 的 extension (先前都是 V2),本來想用 Vue.js 處理設定頁 options.html,但遇到了 CSP 的問題,在 Manifest V3 上面無法設定 unsafe-eval,於是 Vue.js 只能用 runtime 版本,喪失了 template 好用的地方...

後來決定回頭用 jQuery + jQuery UI (用 sortable),然後自己處理一堆 data 更新時頁面的變化,一整個 2010 年老人味都出來了...

但這樣至少會動,先跑一陣子看看...

uBlock Origin 可以修改 DOM event

Hacker News 上看到的「Just normal web things (heather-buchel.com)」這篇,原文「Just normal web things.」本來在抱怨一些 SPA 年代常遇到的問題,但我注意到的反而是討論裡的 id=37018421 這則,介紹了 uBlock Origin 可以修改特定的 DOM event:

New Reddit also messes with text selection with unnecessary JS crap. Wherever you select some text, they show an "Embed" button that prevents you from dragging the text to a new tab to perform a web search.

Thankfully this behaviour can be blocked with uBlock Origin by adding these rules:

  www.reddit.com##+js(aeld, mousedown, isSelectionOutOfRange)
  www.reddit.com##+js(aeld, mouseup, shouldShowButton)

翻了 uBlock Origin 的 wiki 文件,這應該是 aeld.js / addEventListener-defuser.js 這個功能:

Prevents attaching event listeners.

aeld 可以阻止某些事件掛到 DOM 元素上,這感覺好像可以少寫不少 userscript,單純用 uBlock Origin 設條件就可以做到了?

另外在同一頁上 (Resources Library 這頁) 也有其他有趣的東西,像是拔掉 timeout 設定或是某些 attribute 的內容,另外也可以對 API 傳回來的 JSON 或 XML 內容進行刪除某些欄位...

算是意外注意到,後續希望遇到的時候可以想起來...

在 DOM 操作時的 insertAdjacentElement

看到「Why I'm still using jQuery in 2019」這篇,裡面提到了 jQuery 很多操作上相較於 vanilla javascript 簡單很多,其中一個例子提到了 DOM 操作的 insertAdjacentElement()

el.insertAdjacentElement('afterend', other) undoubtedly works, but $(el).after(other) is actually palatable.

其實我不知道 insertAdjacentElement() 這個功能,我知道的操作都是透過 parentElementfirstChild 在移動位置,然後用 appendChild()insertBefore() 放進去。

跑去 MDN 上查了「Element.insertAdjacentElement() - Web APIs | MDN」後才發現有這個好用的東西:

targetElement.insertAdjacentElement(position, element);

position 的四個變化減少了以前組積木組多了會頭暈的情況。

接下來是研究支援度的問題,才發現可能是因為 Firefox 一直到 48 才支援 (從「Firefox version history」可以看到 48 是 2016 年八月釋出),所以網路上大多數的文章都還是用組積木的方式在介紹 DOM 操作,以避免相容性的問題:

Firefox 48 was released on August 2, 2016 for both desktop and Android.

另外還看到 insert​Adjacent​HTML()insert​Adjacent​Text() 可以用,其中讓我注意到 MDN 上面提到 insert​Adjacent​HTML() 居然是 Firefox 8+?本來以為是 48+ 的誤植,但從 Mozilla 的記錄「Implement insertAdjacentHTML」這邊可以看到,應該是在 Firefox 8 的時候實作的,這樣的話可以當作 insertAdjacentElement() 的替代品 (如果考慮到古早的相容性),只是這邊需要輸入 html string,跟其他操作是是用 element 不太一致...

意外的學到不少歷史故事... @_@

HTML5 的 meter 元素...

Zite 上看到 HTML5 的 meter 元素:「The HTML5 meter Element」,這個元素的 spec 在「4.10.17 The meter element」。

用來表示比率的元素,像是 progress bar,或是使用率...

這是直接用你的瀏覽器 render <meter min="0" max="100" value="50"></meter> 的結果:

這是示意圖 (有點大 XD):

依照 caniuse.com 上的說明,比較新的桌面瀏覽器都支援了:「Progress & Meter」。

以往應該都是自己用 div 處理,現在看起來可以用這個元素,再用 JavaScript 對 IE 處理了?