MutationObserver
Azareal opened this issue · comments
Maybe, a MutationObserver might make EQCSS more efficient on newer browsers?
Hi @Azareal, I've thought about using mutation observer for element queries, but the biggest benfits of using it would be:
- for helping
min-children
andmax-children
stay current - possibly for
min-characters
ormin-lines
But the browser support prevents it from being included in EQCSS likely forever. In EQCSS we're using the following JS events, and if you wanted to add a Mutation Observer that called EQCSS.apply()
on your website you might be able to make EQCSS smarter and respond better without having to modify the code of EQCSS itself :D
- Global:
DOMContentLoaded
- Global:
resize
- Global:
input
- Global:
click
- Global:
mousemove
if mouse button held down - Element:
scroll
So it would be easy for you to add Mutation Observer in addition to these.
One area where using an observer might prove better than listening to global events would be to use a ResizeObserver instead of listening to the global resize
event - this should perform better, but right now the only browser to support ResizeObserver is Chrome behind a flag, so it will still be a while before we can release plugins that make use of it.
Here's a small plugin I wrote that uses an EQCSS-like object format to add element queries using ResizeObserver:
const robserv = {}
robserv.data = []
robserv.load = query => {
for (let i=0; i<query.length; i++) {
robserv.data.push(query[i])
}
robserv.apply()
}
robserv.apply = () => {
let ro = new ResizeObserver(entries => {
for (let entry of entries) {
const query = entry.target.getAttribute('data-query')
const count = entry.target.getAttribute('data-tag')
const test = robserv.data[query].test
const stylesheet = robserv.data[query].stylesheet.replace(/\$this/g, `[data-query="${query}"][data-tag="${count}"]`)
const tag = entry.contentRect
const func = new Function(`return ${test}`)
const style = document.querySelector(`#query-${query}-tag-${count}`)
for (item in tag) {
console.log(`${item} ${tag[item]}`)
}
if (func.call(tag)) {
style.innerHTML = stylesheet
} else {
style.innerHTML = ''
}
}
})
for (let query in robserv.data) {
let tag = document.querySelectorAll(robserv.data[query].selector)
let count = 0
if (!robserv.data[query].processed == true) {
for (let j=0; j<tag.length; j++) {
tag[j].setAttribute(`data-query`, query)
tag[j].setAttribute(`data-tag`, count)
ro.observe(tag[j])
let style = document.querySelector(`#query-${query}-tag-${count}`)
if (!style) {
let tag = document.createElement('style')
tag.id = `query-${query}-tag-${count}`
document.head.appendChild(tag)
}
robserv.data[query].processed == true
count++
}
}
}
}
Which could then load queries like this:
robserv.load([
{
selector: '*',
test: 'this.aspectRatio > 16/9',
stylesheet: '$this { background: lime; }'
}
])
Demo of RobServ: https://codepen.io/tomhodgins/pen/MERNEY
Is there a particular site where you're wanting to use EQCSS and Mutation Observers together?
ResizeObserver already in Chrome 64 without a flag:
https://www.chromestatus.com/feature/5705346022637568
I think given how EQCSS is built, and with each feature supporting IE8+ that ResizeObserver probably will forever fall outside of the scope of EQCSS, but it should be possible to build an EQCSS-like plugin that takes advantage of RO in new browsers :)