base-element
An element authoring library for creating standalone and performant elements.
View this example List element in use with:
Or other examples:
example usage
You can construct your element API however you choose. A way that I prefer is
by inheriting prototypes:
var BaseElement = require('base-element')
function Bear () {
BaseElement.call(this)
}
Bear.prototype = Object.create(BaseElement.prototype)
Then build your elements:
Bear.prototype.render = function (typeOfBear) {
var vtree = this.html('div.bear', ['Im a ' + typeOfBear + '!'])
return this.afterRender(vtree)
}
Prefer just functions?
If you prefer just functions, an alternative interface is available:
var createElement = require('base-element')
var el = createElement(document.body)
el.render(function () {
return el.html('button', {
onclick: function (e) {
window.alert(e.target.innerText + ' button was clicked')
}
}, 'click me')
})
data down, events up
DOMs work best (in the opinion of myself and many) when data goes down
and event (or actions) go up.
A simple example is a button element that changes when clicked. How it
changes is up to the element but what it changes to is up to the user.
This is our Button element:
var BaseElement = require('base-element')
function Button () {
BaseElement.call(this)
}
Button.prototype = Object.create(BaseElement.prototype)
Button.prototype.render = function (label) {
var self = this
var vtree = this.html('button', {
onclick: function (event) {
self.send('clicked', event.target)
}
}, label)
return this.afterRender(vtree)
}
and this is the user's implementation, creates a button and on every click it
changes to a random number:
var button = require('your-button')()
button.addEventListener('clicked', function (node) {
button.render('button label ' + Math.random())
})
nested architecture
Elements created using base-element
are intended on being shared and extended
by others. Each element should not require an additional library/framework to
run it or be injected into it in order to be ran. Elements should be standalone.
For example if you create an input-box
element and published on npm:
var BaseElement = require('base-element')
function InputBox (el) {
BaseElement.call(this, el)
}
InputBox.prototype = Object.create(BaseElement.prototype)
module.exports = InputBox
InputBox.prototype.render = function (value) {
return this.afterRender(this.html('input', {
onkeyup: function(e) {
this.send('changed', e.target.value)
}.bind(this),
value: value || ''
}))
}
Later yourself or another user can extend input-box
to add functionality on
top, such as email-input
:
var InputBox = require('input-box')
function EmailInput (el) {
InputBox.call(this, el)
this.addEventListener('changed', function (text) {
})
}
EmailInput.prototype = Object.create(InputBox.prototype)
module.exports = EmailInput
EmailInput.prototype.render = function (data) {
data = data || {}
var vtree = this.html('div', [
this.html('label', data.label || 'Enter your email'),
InputBox.prototype.render(data.value)
])
return this.afterRender(vtree)
}
Both input-box
and email-input
can be ran on their own. When input-box
updates over time, email-input
can stay on a previous version until an upgrade
can be made.
install
npm with browserify, webpack, etc
npm install base-element
var BaseElement = require('base-element')
standalone
- copy/download/etc dist/base-element.js
<script src="base-element.js"></script>
<script>var element = new BaseElement()</script>
api
var element = new BaseElement([attachTo])
attachTo
is a DOM element you want to append to such as document.body
By default, the element will not attach itself to a parent node. This is useful
for handling the rendering on your own.
element.send(name[, params...])
Sends an event up with a given name
and params
.
element.addEventListener(name, function)
Register an event listener for a given name:
element.addEventListener('clicked', function (params) {})
element.afterRender([params...])
This method needs to be called when returning a constructed virtual tree. It
will detect if we are at the top of the render tree and perform the DOM diff
and patching.
Button.prototype.render = function (data) {
var vtree = this.html('button')
return this.afterRender(vtree)
}
element.html(tag[, options], value)
A convenience wrapper for creating virtual-hyperscript nodes, i.e.:
var h = require('virtual-dom/h')
var vtree = h('div', 'Testing')
var vtree = this.html('div', 'Testing')
element.toString([data...])
For rendering your element as a string of HTML. data
is any initial data
passed to your render
function.
element.element
The root DOM node the virtual tree resides on.
element.vtree
The current virtual DOM tree of the base element.
default events
load
and unload
events will be sent by default if your top level element
registers this
as it's properties:
var BaseElement = require('base-element')
function Button(el) {
BaseElement.call(this, el)
this.addEventListener('load', function (node) {
console.log(node + ' has loaded!')
})
this.addEventListener('unload', function (node) {
console.log(node + ' has unloaded!')
})
}
Button.prototype.render = function (data) {
return this.afterRender(this.html('button', this, 'click me'))
}
license
(c) 2015 Kyle Robinson Young. MIT License