diff --git a/examples/editor-bundle/index.html b/examples/editor-bundle/index.html new file mode 100644 index 00000000..d988274e --- /dev/null +++ b/examples/editor-bundle/index.html @@ -0,0 +1,34 @@ + + + + Markdown Editor + + + +
+ + + + + + \ No newline at end of file diff --git a/examples/editor/index.html b/examples/editor/index.html new file mode 100644 index 00000000..c9178f18 --- /dev/null +++ b/examples/editor/index.html @@ -0,0 +1,43 @@ + + + + Markdown Editor + + + +
+ + + + + + + + + \ No newline at end of file diff --git a/examples/threaditjs/app.js b/examples/threaditjs/app.js index d8cb5b00..05085fe6 100644 --- a/examples/threaditjs/app.js +++ b/examples/threaditjs/app.js @@ -3,8 +3,8 @@ T.time("Setup"); var request = require("../../request/request")(window, Promise).ajax var m = require("../../render/hyperscript") var trust = require("../../render/trust") -var render = require("../../render/render")(window, run).render -var router = require("../../router/router")(window, "#") +var renderer = require("../../render/render")(window) +var router = require("../../router/router")(window) //API calls var api = { @@ -178,16 +178,18 @@ var Reply = { } //router +renderer.setEventCallback(run) function run() { replayRoute() } var root = document.getElementById("app") +router.setPrefix("#") var replayRoute = router.defineRoutes({ "/thread/:id" : Thread, "/" : Home }, function(view, args) { - render(root, [m(view, args)]) + renderer.render(root, [m(view, args)]) }, function() { router.setPath("/") }) diff --git a/examples/todomvc/todomvc.js b/examples/todomvc/todomvc.js index 58136282..0aa2d5d5 100644 --- a/examples/todomvc/todomvc.js +++ b/examples/todomvc/todomvc.js @@ -1,6 +1,6 @@ var m = require("../../render/hyperscript") -var render = require("../../render/render")(window, run).render -var router = require("../../router/router")(window, "#") +var renderer = require("../../render/render")(window) +var router = require("../../router/router")(window) //model var todos = loadData() @@ -124,14 +124,16 @@ function view() { var root = document.getElementById("todoapp") var raf +renderer.setEventCallback(run) function run() { cancelAnimationFrame(raf) raf = requestAnimationFrame(function() { saveData() - render(root, view()) + renderer.render(root, view()) }) } +router.setPrefix("#") router.defineRoutes({ "/": "all", "/active": "active", diff --git a/mithril.js b/mithril.js index dd2c1d20..c920b2d5 100644 --- a/mithril.js +++ b/mithril.js @@ -78,6 +78,7 @@ function hyperscript(selector) { } if (typeof selector === "string") return selectorCache[selector](attrs || {}, Node.normalizeChildren(children)) + return Node(selector, attrs && attrs.key, attrs || {}, Node.normalizeChildren(children), undefined, undefined) } @@ -113,10 +114,7 @@ var createRenderer = function($window) { } function createNode(vnode, hooks) { var tag = vnode.tag - if (vnode.attrs) { - if (vnode.attrs.oninit) vnode.attrs.oninit.call(vnode, vnode) - if (vnode.attrs.oncreate) hooks.push(vnode.attrs.oncreate.bind(vnode, vnode)) - } + if (vnode.attrs != null) initLifecycle(vnode.attrs, vnode, hooks) if (typeof tag === "string") { switch (tag) { case "#": return createText(vnode) @@ -184,8 +182,10 @@ var createRenderer = function($window) { return element } function createComponent(vnode, hooks) { + vnode.state = copy(vnode.tag) + initLifecycle(vnode.tag, vnode, hooks) - vnode.instance = Node.normalize(vnode.tag.view.call(vnode, vnode)) + vnode.instance = Node.normalize(vnode.tag.view.call(vnode.state, vnode)) var element = createNode(vnode.instance, hooks) vnode.dom = vnode.instance.dom vnode.domSize = vnode.instance.domSize @@ -324,7 +324,7 @@ var createRenderer = function($window) { } } function updateComponent(parent, old, vnode, hooks, nextSibling, recycling) { - vnode.instance = Node.normalize(vnode.tag.view.call(vnode, vnode)) + vnode.instance = Node.normalize(vnode.tag.view.call(vnode.state, vnode)) updateLifecycle(vnode.tag, vnode, hooks, recycling) updateNode(parent, old.instance, vnode.instance, hooks, nextSibling, recycling) vnode.dom = vnode.instance.dom @@ -545,6 +545,20 @@ var createRenderer = function($window) { } return false } + + function copy(data) { + if (data instanceof Array) { + var output = [] + for (var i = 0; i < data.length; i++) output[i] = copy(data[i]) + return output + } + else if (typeof data === "object") { + var output = {} + for (var i in data) output[i] = copy(data[i]) + return output + } + return data + } function render(dom, vnodes) { var hooks = [] @@ -564,13 +578,15 @@ var createRenderer = function($window) { var createMounter = function($window, redraw) { return function(root, component) { - var render = createRenderer($window, draw).render + var renderer = createRenderer($window) + renderer.setEventCallback(draw) function draw() { - render(root, component) + renderer.render(root, {tag: component}) } - redraw.run = redraw + redraw.run = draw + draw() } } diff --git a/mount.js b/mount.js index d6a0665b..3a389ba0 100644 --- a/mount.js +++ b/mount.js @@ -2,12 +2,14 @@ var createRenderer = require("./render/render") module.exports = function($window, redraw) { return function(root, component) { - var render = createRenderer($window, draw).render + var renderer = createRenderer($window) + renderer.setEventCallback(draw) function draw() { - render(root, component) + renderer.render(root, {tag: component}) } - redraw.run = redraw + redraw.run = draw + draw() } } \ No newline at end of file diff --git a/render/hyperscript.js b/render/hyperscript.js index 58f8f3d5..8b407075 100644 --- a/render/hyperscript.js +++ b/render/hyperscript.js @@ -63,6 +63,7 @@ function hyperscript(selector) { } if (typeof selector === "string") return selectorCache[selector](attrs || {}, Node.normalizeChildren(children)) + return Node(selector, attrs && attrs.key, attrs || {}, Node.normalizeChildren(children), undefined, undefined) } diff --git a/render/render.js b/render/render.js index 2c0eb925..0c54d084 100644 --- a/render/render.js +++ b/render/render.js @@ -87,8 +87,10 @@ module.exports = function($window) { return element } function createComponent(vnode, hooks) { + vnode.state = copy(vnode.tag) + initLifecycle(vnode.tag, vnode, hooks) - vnode.instance = Node.normalize(vnode.tag.view.call(vnode, vnode)) + vnode.instance = Node.normalize(vnode.tag.view.call(vnode.state, vnode)) var element = createNode(vnode.instance, hooks) vnode.dom = vnode.instance.dom vnode.domSize = vnode.instance.domSize @@ -227,7 +229,7 @@ module.exports = function($window) { } } function updateComponent(parent, old, vnode, hooks, nextSibling, recycling) { - vnode.instance = Node.normalize(vnode.tag.view.call(vnode, vnode)) + vnode.instance = Node.normalize(vnode.tag.view.call(vnode.state, vnode)) updateLifecycle(vnode.tag, vnode, hooks, recycling) updateNode(parent, old.instance, vnode.instance, hooks, nextSibling, recycling) vnode.dom = vnode.instance.dom @@ -448,6 +450,20 @@ module.exports = function($window) { } return false } + + function copy(data) { + if (data instanceof Array) { + var output = [] + for (var i = 0; i < data.length; i++) output[i] = copy(data[i]) + return output + } + else if (typeof data === "object") { + var output = {} + for (var i in data) output[i] = copy(data[i]) + return output + } + return data + } function render(dom, vnodes) { var hooks = [] diff --git a/render/tests/test-input.js b/render/tests/test-input.js index 401895d8..ebff4147 100644 --- a/render/tests/test-input.js +++ b/render/tests/test-input.js @@ -14,6 +14,7 @@ o.spec("form inputs", function() { }) o.afterEach(function() { while (root.firstChild) root.removeChild(root.firstChild) + root.vnodes = null }) o.spec("input", function() {