Skip to content

🔰 An element authoring library for creating standalone and performant elements.

Notifications You must be signed in to change notification settings

yoshuawuyts/base-element

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

75 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

base-element

An element authoring library for creating standalone and performant elements.

build status NPM version experimental

Sauce Test Status

View this example List element in use with:

Or other examples:

example usage

Create a generic JavaScript "class" that inherits BaseElement:

var BaseElement = require('base-element')

function Bear () {
  BaseElement.call(this)
}
Bear.prototype = Object.create(BaseElement.prototype)
// Or inherits(Bear, BaseElement)
// Or class Bear extends BaseElement

Then build your elements:

Bear.prototype.render = function (typeOfBear) {
  // Create a virtual DOM tree
  var vtree = this.html('div.bear', ['Im a ' + typeOfBear + '!'])
  // Call afterRender with your vtree when returning your vtree
  return this.afterRender(vtree)
}

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)
// Or inherits(Button, BaseElement)
// Or class Button extends BaseElement

Button.prototype.render = function (label) {
  var self = this
  // The "label" data is coming down
  var vtree = this.html('button', {
    onclick: function (event) {
      // We send the "clicked" event up
      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.on('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 I 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) {
  // Builds an <input value="{value}: />
  return this.afterRender(this.html('input', {
    onkeyup: function(e) {
      // When keys are typed in it we send the value up
      this.send('changed', e.target.value)
    }.bind(this),
    value: value || ''
  }))
}

Now yourself or another user can either consume your input-box or extend it to add their own functionality on top of yours, such as email-input:

var InputBox = require('input-box')
function EmailInput (el) {
  InputBox.call(this, el)

  // When we receive a "changed" event from InputBox, handle it here
  this.on('changed', function (text) {
    /* Perform some email validation on text here,
       then render() if we need an update */
  })
}
EmailInput.prototype = Object.create(InputBox.prototype)
module.exports = EmailInput

EmailInput.prototype.render = function (data) {
  data = data || {}
  var vtree = this.html('div', [
    // Put a <label>Enter your email</label> inside this <div>
    this.html('label', data.label || 'Enter your email'),
    // Call the InputBox's render
    InputBox.prototype.render(data.value)
  ])
  // Return the virtual DOM tree
  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. Defaults to document.body.

If you pass in false then the element will not automatically append itself to a parent node. This is useful if you plan on handling the rendering of the virtual tree on your own.

element.send(name[, params...])

Sends an event up with a given name and params.

element.on(name, function)

Register an event listener for a given name:

element.on('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 tree = 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')

// is the same as
var vtree = this.html('div', 'Testing')

element.element

The root DOM node the virtual tree resides on.

element.vtree

The current virtual DOM tree of the base element.

license

(c) 2015 Kyle Robinson Young. MIT License

About

🔰 An element authoring library for creating standalone and performant elements.

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages

  • JavaScript 100.0%