choo: add href / history handling

This commit is contained in:
Yoshua Wuyts
2016-05-12 14:45:20 +07:00
parent 049d8f0cee
commit 53a1e6026a
4 changed files with 61 additions and 34 deletions
+5 -2
View File
@@ -5,7 +5,7 @@ sf('css-wipe/dest/bundle')
sf('tachyons') sf('tachyons')
const mainView = require('./views/main') const mainView = require('./views/main')
const navElement = require('./elements/nav') const nav = require('./elements/nav')
const app = choo() const app = choo()
@@ -14,7 +14,10 @@ app.model('spam', require('./models/spam'))
app.model('sent', require('./models/sent')) app.model('sent', require('./models/sent'))
app.router((route) => [ app.router((route) => [
route('/', mainView(navElement)) route('/', mainView(nav)),
route('/:mailbox', mainView(nav), [
route('/:message_id', mainView(nav))
])
]) ])
const tree = app.start() const tree = app.start()
+15
View File
@@ -0,0 +1,15 @@
module.exports = {
state: {
messages: [
{
id: 4,
subject: 'Should I use Ember',
from: 'user@example.com',
to: 'tomster@emberjs.com',
date: new Date(),
body: 'Ember looks pretty good, should I use it?'
}
]
},
reducers: { }
}
+2 -1
View File
@@ -3,9 +3,10 @@ const choo = require('../../../')
module.exports = function (nav) { module.exports = function (nav) {
return function (params, state, send) { return function (params, state, send) {
console.log(state)
return choo.view` return choo.view`
<main class="app"> <main class="app">
<span>URL: ${pathname(state.location) || '/'}</span> <span>URL: ${'/' + pathname(state.location)}</span>
${nav(params, state, send)} ${nav(params, state, send)}
<section> <section>
<table> <table>
+39 -31
View File
@@ -1,9 +1,8 @@
// const history = require('sheet-router/history') const history = require('sheet-router/history')
const sheetRouter = require('sheet-router') const sheetRouter = require('sheet-router')
const document = require('global/document') const document = require('global/document')
// const href = require('sheet-router/href') const href = require('sheet-router/href')
const sendAction = require('send-action') const sendAction = require('send-action')
const mutate = require('xtend/mutable')
const xtend = require('xtend') const xtend = require('xtend')
const yo = require('yo-yo') const yo = require('yo-yo')
@@ -12,7 +11,9 @@ module.exports = choo
// A framework for creating sturdy web applications // A framework for creating sturdy web applications
// null -> fn // null -> fn
function choo () { function choo (opts) {
opts = opts || {}
const name = opts.name || 'choo'
var _router = null var _router = null
var _models = [ appInit() ] var _models = [ appInit() ]
@@ -27,20 +28,33 @@ function choo () {
function start () { function start () {
const events = bootstrap(_models) const events = bootstrap(_models)
const send = sendAction({ const send = sendAction({
onaction: events.middleware, onaction: events.modifyState,
onchange: onchange, onchange: onchange,
state: events.state state: events.state
}) })
if (opts.href !== false) {
href(function (href) {
send('location', { location: href })
})
}
if (opts.history !== false) {
history(function (href) {
send('location', { location: href })
})
}
const rootId = name + '-root'
const tree = _router(send.state().location, send.state(), send) const tree = _router(send.state().location, send.state(), send)
tree.setAttribute('id', 'choo-root') tree.setAttribute('id', rootId)
return tree return tree
// update on every change // update on every change
function onchange (action, state) { function onchange (action, state) {
const oldTree = document.querySelector('#choo-root') const oldTree = document.querySelector('#' + rootId)
const newTree = _router(state.location, state, send) const newTree = _router(state.location, state, send)
newTree.setAttribute('id', 'choo-root') newTree.setAttribute('id', rootId)
yo.update(oldTree, newTree) yo.update(oldTree, newTree)
} }
} }
@@ -60,6 +74,8 @@ function choo () {
} }
} }
// initial application state model
// null -> obj
function appInit () { function appInit () {
return { return {
state: { state: {
@@ -78,35 +94,18 @@ function appInit () {
} }
function bootstrap (events) { function bootstrap (events) {
const initialState = { } const initialState = {}
const reducers = {} const reducers = {}
const effects = {} const effects = {}
events.forEach(function (event) { events.forEach(function (model) {
const name = event.name if (model.state) apply(model.name, model.state, initialState)
if (event.state) mutate(initialState, event.state) if (model.reducers) apply(model.name, model.reducers, reducers)
if (event.reducers) { if (model.effects) apply(model.name, model.effects, effects)
Object.keys(event.reducers).forEach(function (key) {
if (name) {
reducers[name + ':' + key] = event.reducers[key]
} else {
reducers[key] = event.reducers[key]
}
})
}
if (event.effects) {
Object.keys(event.effects).forEach(function (key) {
if (name) {
effects[name + ':' + key] = event.effects[key]
} else {
effects[key] = event.effects[key]
}
})
}
}) })
return { return {
middleware: modifyState, modifyState: modifyState,
state: initialState state: initialState
} }
@@ -133,3 +132,12 @@ function bootstrap (events) {
return newState return newState
} }
} }
// compose an object conditionally
// (str, obj, obj) -> null
function apply (name, source, target) {
Object.keys(source).forEach(function (key) {
if (name) target[name + ':' + key] = source[key]
else target[key] = source[key]
})
}