Skip to content

Instantly share code, notes, and snippets.

@jon49
Last active August 23, 2025 08:10
Show Gist options
  • Select an option

  • Save jon49/28f84694272e39e2b642efa69b507c6e to your computer and use it in GitHub Desktop.

Select an option

Save jon49/28f84694272e39e2b642efa69b507c6e to your computer and use it in GitHub Desktop.
Web component adder
const elHandler = {
get(obj, prop) {
if (prop[0] === "$") {
return obj[prop.slice(1)]
}
let val = obj[prop]
if (!(val instanceof HTMLElement)) return
if (isInputElement(val)) {
if (val.type === "number") {
return +val.value
}
return val.value
}
return val.textContent
},
set(obj, prop, newVal) {
let val = obj[prop]
if (!(val instanceof HTMLElement)) return false
if (isInputElement(val)) {
val.value = newVal
return true
}
val.textContent = newVal
return true
}
}
function isInputElement(obj) {
return obj instanceof HTMLInputElement || obj instanceof HTMLSelectElement
}
export function getXElements(fragment) {
let o = {}
for (let el of fragment.querySelectorAll(`[x]`)) {
o[el.getAttribute('x') || ''] = el
el.removeAttribute('x')
}
return new Proxy(o, elHandler)
}
export function handleEvent(context, event) {
let target = event.target
if (target instanceof HTMLElement) {
// @ts-ignore
let action = target.dataset.action || target.closest('[data-action]')?.dataset?.action
if (action) {
if (context[action] instanceof Function) {
requestAnimationFrame(() => {
context[action](event)
})
event.stopPropagation()
event.preventDefault()
} else {
console.error(`Action ${action} not implemented.`)
}
} else if (context[event.type] instanceof Function) {
context[event.type](event)
event.stopPropagation()
event.preventDefault()
}
}
}
import { handleEvent, getXElements } from "./adder-libs.js"
class Adder extends HTMLElement {
constructor() {
super()
this.$ = getXElements(this)
this.addEventListener('input', this)
}
handleEvent(event) {
handleEvent(this, event)
}
add() {
let $ = this.$
$.target = `${$.num1} + ${$.num2} = ${$.num1 + $.num2}`
}
}
customElements.define('x-adder', Adder)
<!DOCTYPE html>
<html lang="en">
<head>
<title>Adder</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h1>Add numbers!</h1>
<x-adder>
<input x=num1 data-action=add type="number">
<input x=num2 data-action=add type="number">
<p x=target></p>
</x-adder>
<script type=module src="./adder.js"></script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment