eqcss / eqcss

EQCSS is a CSS Reprocessor that introduces Element Queries, Scoped CSS, a Parent selector, and responsive JavaScript to all browsers IE8 and up

Home Page:https://elementqueries.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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 and max-children stay current
  • possibly for min-characters or min-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?

commented

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 :)