-
Notifications
You must be signed in to change notification settings - Fork 0
/
better.js
71 lines (65 loc) · 2.27 KB
/
better.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
export default class extends HTMLElement {
constructor() {
super()
if (this.constructor.shadow) this.attachShadow({mode: 'open'})
let object = this
}
get root() {
return this.shadowRoot || this
}
connectedCallback() {
if ("onConnect" in this) this.onConnect()
this.dispatchEvent(new Event("connected"))
}
disconnectedCallback() {
if ("onDisconnect" in this) this.onDisonnect()
this.dispatchEvent(new Event("disconnected"))
}
set content(content) {
this.root.replaceChildren(content)
}
attributeChangedCallback(attr, old, value) {
let name = attr.replace(/-([a-z])/, (_, l) => l.toUpperCase())
let attribute = this.constructor.attributes[name]
if (name+"Changed" in this)
if (typeof(attribute.get) == "function")
this[name+"Changed"](attribute.get.call(this, value), attribute.get.call(this, old))
else
this[name+"Changed"](value, old)
}
// Adds property/attribute mappings to the object.
static initialise(name = this.name) {
let attributes = this.attributes
? [...Object.keys(this.attributes)]
: []
/* See HTMLElement API */
Object.defineProperty(this, "observedAttributes", {
get() { return attributes.map(attr => attr.replace(/[A-Z]/, u => "-"+u.toLowerCase())) }
})
attributes.forEach(name => {
let attribute = this.attributes[name]
let htmlName = name.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase()
let prop = {}
/* Is there a get filter? */
if (typeof attribute.get == "function")
prop.get = function() { return attribute.get.call(this, this.getAttribute(htmlName)) }
else
prop.get = function() { return this.getAttribute(htmlName) }
/* Is there a set filter? */
if (typeof attribute.set == "function")
prop.set = function(val) { return this.setAttribute(htmlName, attribute.set.call(this, val)) }
else if (attribute.set === false)
prop.set = function(val) { throw(`Attribute ${name} cannot be set`) }
else
prop.set = function(val) { this.setAttribute(htmlName, val) }
Object.defineProperty(this.prototype, name, prop)
})
name = name.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase()
if (this.extends)
customElements.define(name, this, { extends: this.extends })
else
customElements.define(name, this)
return name
}
static initialize(name) { this.initialise(name) }
}