Help developer to track changes in the content script
Looking for Documentation?
Let's look an example.
Here we have a train ticket that generated by React. It will automatically refresh, just like today's PWAs.
You want to add price in USD after every ticket.
import { LiveSelector, MutationObserverWatcher } from '@holoflows/kit/DOM'
const price = new LiveSelector()
// Select all .ticket-row
.querySelector<HTMLDivElement>('.ticket-row')
// Remove all that doesn't have Euro symbol
.filter(x => x.innerText.match('€'))
// map element to its inner .price
.map(x => x.querySelector('.price'))
function EuroToUSD(x: number) {
return x * 1.13
}
new MutationObserverWatcher(price, document.querySelector('#main'))
.useForeach((node, key, meta) => {
const addPrice = () => (meta.after.innerText = '$' + EuroToUSD(parseInt(node.innerText)))
addPrice()
return {
onNodeMutation: addPrice,
}
})
.startWatch()
Done! Everytime that a new ticket appears, price in US will be added after it. But wait, it goes to far, I'm confused!
Okay, that's a just regular usage, shows how @holoflows/kit can help you.
After you read the intros, and back, you will understand these.
LiveSelector is a convenient tool, to help you "compute" the same selector at any time. It looks like Array.
const ls = new LiveSelector()
ls.querySelectorAll('a') // Select all `a`
ls.filter(x => x.href.startsWith('https://')) // Remove all link that not starts with https://
ls.map(x => x.href) // map HTMLAnchorElement[] to string[]
ls.evaluate() // return all links on the page currently
setTimeout(() => {
ls.evaluate() // yeah it will match all links every time so you always get the latest data!
})
About the full documentation, see: LiveSelector。
Then what is MutationObserverWatcher
??
In short words, it can watch the change of something.
There are several kinds of Watcher:- MutationObserverWatcher (Using MutationObserver)
- IntervalWatcher (Using setInterval)
- EventWatcher (Call it manually)
All Watcher's usage is the same:
- To let it watch, call
startWatch()
- To stop it, call
stopWatch()
In general, Watchers watch for changes of DOM. If you want to watch anything else, that's okay, Watcher provides some events like onAdd
onRemove
, See Watcher。
Here is how we watch dom changing. If you have used React hooks, this is just like React hooks.
A complete useForeach
call is like this:
.useForeach((node, key, meta) => {
// Code here, will be called **every time** when a new element E comes into the list. Here are parameters:
node // A DOMProxy, just like a DOM node (Yeah it's magic!)
meta.before // A <span> that always point to the before of E
meta.after // A <span> that always point to the after of E
meta.current // It is node(the first parameter), it always points to E, even E has changed, it "reference" will be "update" (Not actually, see documentation of DOMProxy)
key // Have you use React, Vue or Angular? When rendering lists, they will ask for you to provide a key to identify what is not changed.
meta.realCurrent // Sometimes you want to access the real dom. Then use it.
return {
onRemove(old) {
// When E is gone...
// What you need to do?
// Like React.useEffect(() => { return `function here` })
},
onNodeMutation() {
// When key is not changed, E is not changed too.
// But here is change in the E
// Like a new element is inserted into node.current
},
onTargetChanged(newNode, oldNode) {
// If key is not changed, but E is changed.
// Notice: node.current always points to the new node, so you may not need to handle this
},
}
})
Tips: If you only care about the first element in the
LiveSelector
, here is a shortcut!Watcher#firstDOMProxy
is aDOMProxy
and it will always points to the first element in the list!