Skip to content

Instantly share code, notes, and snippets.

@madx
Last active August 29, 2015 14:19
Show Gist options
  • Save madx/c2d009d1d92be7bd38b7 to your computer and use it in GitHub Desktop.
Save madx/c2d009d1d92be7bd38b7 to your computer and use it in GitHub Desktop.
Component class
import {isObject} from "./utils"
import Dispatcher from "./dispatcher"
export default class Component {
constructor() {
this.rootNode = null
this.props = {}
// Add dispatcher observers
if (this.constructor.observers) {
const observers = this.constructor.observers
for (let eventName in observers) {
const methodName = observers[eventName]
Dispatcher.addObserver(eventName, this, methodName)
}
}
}
destroy() {
if (this.rootNode.parentNode) {
this.rootNode.parentNode.removeChild(this.rootNode)
}
// Remove dispatcher observers
const observers = this.constructor.observers
if (observers) {
for (let eventName in observers) {
Dispatcher.removeObserver(eventName, this)
}
}
}
// Define an updatable property of the component.
// Also updates the property if it's already set
prop(propName, propValue = "") {
let propNode = this.props[propName]
if (!propNode) {
propNode = this.props[propName] = document.createTextNode(propValue)
}
if (propValue !== propNode.textContent) {
propNode.textContent = propValue
}
return propNode
}
render() {
if (this.rootNode) {
throw new Error("already rendered component")
}
if (!this.build) {
throw new Error("unimplemented method build()")
}
this.rootNode = this.build()
// Add DOM event handlers
const eventHandlers = this.constructor.eventHandlers
if (eventHandlers) {
for (let eventName in eventHandlers) {
const handler = eventHandlers[eventName]
this.rootNode.addEventListener(eventName, handler.bind(this), true)
}
}
return this.rootNode
}
show() {
this.rootNode.classList.toggle("u-hidden", false)
}
hide() {
this.rootNode.classList.toggle("u-hidden", true)
}
toggle() {
console.warn("hello", this.rootNode)
this.rootNode.classList.toggle("u-hidden")
}
static tag(tagSpec, attributes, children) {
if (!tagSpec) {
throw new Error("No tagSpec given")
}
attributes = attributes || {}
children = children || []
if (!isObject(attributes)) {
children = attributes
attributes = {}
}
const [tagName, className] = tagSpec.split(".")
const node = document.createElement(tagName)
if (className) {
node.classList.add(className)
}
if (!(children instanceof Array)) {
children = [children]
}
for (let attrName in attributes) {
node.setAttribute(attrName, attributes[attrName])
}
for (let child of children) {
if (typeof child === "object" && "render" in child) {
// Component children
child.render()
node.appendChild(child.rootNode)
} else if (typeof child === "string") {
// Text children
node.appendChild(document.createTextNode(child))
} else {
// DOM nodes children
node.appendChild(child)
}
}
return node
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment