minichoo
v1.0.2
Published
a smaller, standalone version of choo without using any virtual DOM
Downloads
2
Readme
minichoo
a smaller (10KB bundle), standalone version of choo without using any virtual DOM
assumptions
this library assumes there is a div with an id of "app" to mount the app too. this library assumes the browser is modern but should work ok with babel-polyfill
idea
- when you want choo but smaller and without node api or babel polyfill
- live off the land: use template strings directly and completely avoid the virtual DOM
- make it attach to the window like jquery suitable for a small script tag dependency
- no need to bundle or build
todo:
- add examples for using forms
- finish documentation
- allow mount to attach to any DOM element
- scrutinize use of innerHTML and template strings for security issues!
- security review and audit
- create version using commonjs modules suitable for browserify
include in a html page
<link rel="stylesheet" href="https://unpkg.com/tachyons/css/tachyons.min.css">
<script src="https://unpkg.com/[email protected]/minichoo.min.js"></script>
<div id="app"></div>
example
var app = minichoo()
app.use(function (state, emitter) {
state.demo = 1;
})
app.route('/', function (state, emitter) {
state.ready(() => {
console.log('dom is ready')
})
window.increment = function () {
state.demo++; // this does not re-render the page automatically
// this is a cheap trick to re-render the page
window.location = '#/'
}
return `
<article class="vh-100 dt w-100 bg-dark-pink">
<div class="dtc v-mid tc white ph3 ph4-l">
<h1 class="f6 f2-m f-subheadline-l fw6 tc">minichoo :: demo: ${state.demo}</h1>
<a href="#!" class="f6 link dim br1 ba bw2 ph3 pv2 mb2 dib navy" onclick="window.increment()">increment</a>
<a class="f6 link dim br1 ba bw2 ph3 pv2 mb2 dib navy" href="#/page2">go to page 2</a>
</div>
</article>
`
})
app.route('/page2', function () {
return `<article class="vh-100 dt w-100 bg-dark-pink">
<div class="dtc v-mid tc white ph3 ph4-l">
<h1 class="f6 f2-m f-subheadline-l fw6 tc">minichoo :: page 2</h1>
<a class="f6 link dim br1 ba bw2 ph3 pv2 mb2 dib navy" href="#/">go home</a>
</div>
</article>`
})
app.mount()
minichoo
this is the minichoo source code without deps: (nanorouter and nanobus)...
// minichoo
//
function minichoo () {
if (! (this instanceof minichoo)) return new minichoo ()
this.middleware = []
this.routes = {}
this.state = {}
this.params = {}
var self = this
this.emitter = Nanobus()
this.router = Nanorouter()
setTimeout(() => {
this.app = document.getElementById("app")
})
window.onhashchange = function() {
var current_route = location.hash.replace(/\#/g, '') || '/#';
// <a href="#!" will be ignored...
if (!current_route.includes('!')) self.router.emit(current_route)
}
}
minichoo.prototype._finish_setup = function () {
var self = this
Object.keys(self.routes).forEach(function (route) {
self.router.on(route, function (params) {
self.state.params = params
self.app.innerHTML = self.routes[route](self.state, self.emitter)
})
})
}
minichoo.prototype.use = function (middleware) {
assert.ok(typeof middleware === 'function')
this.middleware.push(middleware)
}
minichoo.prototype.route = function (route, handler) {
assert.ok(typeof route === 'string')
assert.ok(typeof handler === 'function')
this.routes[route] = handler;
}
minichoo.prototype.mount = function (element) {
var self = this;
var default_middleware = function (state, emit) {
state.ready = function (...args) { return setTimeout(...args); }
state.form = function addForm (id, callback) {
var form = document.getElementById(id)
form.addEventListener('submit', function (e) {
e.preventDefault()
var data = new FormData(e.currentTarget)
callback(data, e)
})
}
}
default_middleware(self.state, self.emitter)
self.middleware.forEach(function (middleware) {
middleware(self.state, self.emitter)
})
self._finish_setup()
setTimeout(function () {
self.app.innerHTML = self.routes[
Object.keys(self.routes)[0]
](self.state, self.emitter)
}, 1000)
}
window.minichoo = minichoo;
gotchas
- uses hash based routing so you must do this:
<a href="#/some-route"
instead of<a href="/some-route"