zilk/hydrate

attach event listeners to elements


Based on wicked-elements by @WebReflection

Available Handlers

{
  // runs first: setup
  init(){},

  // event listeners for this element
  onClick(event){},
  // listener options
  onClickOptions:{once:true},
  // custom events too
  onSpecial(event){},
  // will respond to `element.dispatchEvent(new CustomEvent('special'))`

  // element lifecycle
  connected(){},
  disconnected(){},

  // invokes attributeChanged() for included attributes
  observedAttributes: ['data-item','value'],
  attributeChanged(name,prev,value){},
}

Helpers

  • this.el: reference to the hydrated element
  • this.$(): like element.querySelector()
  • this.$$(): like [...element.querySelectorAll()]

hydrate(...defs)

Accepts an array of definition objects with {classname:handler} format. On the browser, it registers each queryselector to its handler - automatically hydrating matching elements.

This API was made to keep hydration.js short and simple

(easiest to show by example)

hydration.js

(typically generated programmatically based on files in views/**.js)

import { hydrate } from 'zilk/hydrate'
import { handlers as $h1 } from '../views/MyButton.js'
import { handlers as $h2 } from '../views/MyCard.js'
hydrate($h1,$h2)

index.html

<head>
  <!-- import the hydration script -->
  <script src="/hydration.js" type="module"></script>
</head>
<body>
  <!-- ... -->
</body>

MyCard.js

import { classify } from 'zilk'

// scoped classes: MyCard__WRAP, MyCard__TITLE, MyCard__ITEM
let { WRAP, TITLE, ITEM } = classify('MyCard')

// generate html
export default ({
  title='ssr',
  items=['1','2','3','4','5','6']
}) => html`
  <div class=${WRAP}>
    <h1 class=${TITLE}>${title}</h1>
    <ul class=${ITEM.WRAP}>
      ${items.map(item => html`
        <li class=${ITEM}>${item}</li> 
      `)}
    </ul>
  </div>
`

// hydrate elements
export let handlers = {
  [WRAP]: {
    init(){
      this.setup()
    },
    setup(){
      this.$(TITLE).innerText = 'Hydrated'
      this.$$(ITEMS).forEach((item,i) => {
        item.style.cssText = `background:hsl(${i * 20},70%,40%)`
      })
    }
  }
}