Merge remote-tracking branch 'origin/next' into components

This commit is contained in:
Leo Horie 2015-03-31 10:50:41 -04:00
commit ba26db057e
3 changed files with 70 additions and 22 deletions

View file

@ -498,6 +498,8 @@ m.module(document, {controller: todo.controller, view: todo.view});
--- ---
This example is also available as a [jsFiddle](http://jsfiddle.net/milesmatthias/fbgypzbr/1/).
## Notes on Architecture ## Notes on Architecture
Idiomatic Mithril code is meant to apply good programming conventions and be easy to refactor. Idiomatic Mithril code is meant to apply good programming conventions and be easy to refactor.

View file

@ -129,7 +129,6 @@ var m = (function app(window, undefined) {
//2) add new keys to map and mark them for addition //2) add new keys to map and mark them for addition
//3) if key exists in new list, change action from deletion to a move //3) if key exists in new list, change action from deletion to a move
//4) for each key, handle its corresponding action as marked in previous steps //4) for each key, handle its corresponding action as marked in previous steps
//5) copy unkeyed items into their respective gaps
var DELETION = 1, INSERTION = 2 , MOVE = 3; var DELETION = 1, INSERTION = 2 , MOVE = 3;
var existing = {}, unkeyed = [], shouldMaintainIdentities = false; var existing = {}, unkeyed = [], shouldMaintainIdentities = false;
for (var i = 0; i < cached.length; i++) { for (var i = 0; i < cached.length; i++) {
@ -139,11 +138,14 @@ var m = (function app(window, undefined) {
} }
} }
data = data.filter(function(x) {return x != null})
var guid = 0 var guid = 0
for (var i = 0, len = data.length; i < len; i++) { for (var i = 0, len = data.length; i < len; i++) {
if (data[i] && data[i].attrs && data[i].attrs.key == null) data[i].attrs.key = "__mithril__" + guid++ if (data[i] && data[i].attrs && data[i].attrs.key != null) {
for (var j = 0, len = data.length; j < len; j++) {
if (data[j] && data[j].attrs && data[j].attrs.key == null) data[j].attrs.key = "__mithril__" + guid++
}
break
}
} }
if (shouldMaintainIdentities) { if (shouldMaintainIdentities) {
@ -169,7 +171,6 @@ var m = (function app(window, undefined) {
element: cached.nodes[existing[key].index] || $document.createElement("div") element: cached.nodes[existing[key].index] || $document.createElement("div")
} }
} }
else unkeyed.push({index: i, element: parentElement.childNodes[i] || $document.createElement("div")})
} }
} }
var actions = [] var actions = []
@ -199,12 +200,6 @@ var m = (function app(window, undefined) {
newCached.nodes[change.index] = change.element newCached.nodes[change.index] = change.element
} }
} }
for (var i = 0, len = unkeyed.length; i < len; i++) {
var change = unkeyed[i];
parentElement.insertBefore(change.element, parentElement.childNodes[change.index] || null);
newCached[change.index] = cached[change.index]
newCached.nodes[change.index] = change.element
}
cached = newCached; cached = newCached;
} }
} }

View file

@ -1045,7 +1045,7 @@ function testMithril(mock) {
test(function() { test(function() {
var root = mock.document.createElement("div") var root = mock.document.createElement("div")
m.render(root, m("div", [undefined])) m.render(root, m("div", [undefined]))
return root.childNodes[0].childNodes.length === 0 return root.childNodes[0].childNodes[0].nodeValue == ""
}) })
test(function() { test(function() {
var root = mock.document.createElement("div") var root = mock.document.createElement("div")
@ -1068,19 +1068,19 @@ function testMithril(mock) {
var root = mock.document.createElement("div") var root = mock.document.createElement("div")
m.render(root, m("ul", [m("li")])) m.render(root, m("ul", [m("li")]))
m.render(root, m("ul", [m("li"), undefined])) m.render(root, m("ul", [m("li"), undefined]))
return root.childNodes[0].childNodes.length == 1 return root.childNodes[0].childNodes[1].nodeValue == ""
}) })
test(function() { test(function() {
var root = mock.document.createElement("div") var root = mock.document.createElement("div")
m.render(root, m("ul", [m("li"), m("li")])) m.render(root, m("ul", [m("li"), m("li")]))
m.render(root, m("ul", [m("li"), undefined])) m.render(root, m("ul", [m("li"), undefined]))
return root.childNodes[0].childNodes.length == 1 return root.childNodes[0].childNodes[1].nodeValue == ""
}) })
test(function() { test(function() {
var root = mock.document.createElement("div") var root = mock.document.createElement("div")
m.render(root, m("ul", [m("li")])) m.render(root, m("ul", [m("li")]))
m.render(root, m("ul", [undefined])) m.render(root, m("ul", [undefined]))
return root.childNodes[0].childNodes.length == 0 return root.childNodes[0].childNodes[0].nodeValue == ""
}) })
test(function() { test(function() {
var root = mock.document.createElement("div") var root = mock.document.createElement("div")
@ -1263,18 +1263,18 @@ function testMithril(mock) {
m.render(root, m("div", [m("button"), m("ul")])) m.render(root, m("div", [m("button"), m("ul")]))
var valueBefore = root.childNodes[0].childNodes[0].nodeName var valueBefore = root.childNodes[0].childNodes[0].nodeName
m.render(root, m("div", [undefined, m("ul")])) m.render(root, m("div", [undefined, m("ul")]))
var valueAfter = root.childNodes[0].childNodes[0].nodeName var valueAfter = root.childNodes[0].childNodes[0].nodeValue
return valueBefore === "BUTTON" && valueAfter === "UL" return valueBefore === "BUTTON" && valueAfter === ""
}) })
test(function() { test(function() {
var root = mock.document.createElement("div") var root = mock.document.createElement("div")
m.render(root, m("div", [m("ul"), undefined])) m.render(root, m("div", [m("ul"), undefined]))
var valueBefore1 = root.childNodes[0].childNodes[0].nodeName var valueBefore1 = root.childNodes[0].childNodes[0].nodeName
var valueBefore2 = root.childNodes[0].childNodes.length var valueBefore2 = root.childNodes[0].childNodes[1].nodeValue
m.render(root, m("div", [undefined, m("ul")])) m.render(root, m("div", [undefined, m("ul")]))
var valueAfter1 = root.childNodes[0].childNodes[0].nodeName var valueAfter1 = root.childNodes[0].childNodes[0].nodeValue
var valueAfter2 = root.childNodes[0].childNodes.length var valueAfter2 = root.childNodes[0].childNodes[1].nodeName
return valueBefore1 === "UL" && valueAfter1 === "UL" && valueBefore2 === 1 && valueAfter2 === 1 return valueBefore1 === "UL" && valueAfter1 === "" && valueBefore2 === "" && valueAfter2 === "UL"
}) })
test(function() { test(function() {
//https://github.com/lhorie/mithril.js/issues/79 //https://github.com/lhorie/mithril.js/issues/79
@ -1716,7 +1716,7 @@ function testMithril(mock) {
var root = mock.document.createElement("div") var root = mock.document.createElement("div")
m.render(root, m("div", [m("div", 1), m("div", 2), [m("div", {key: 3}, 3), m("div", {key: 4}, 4), m("div", {key:5}, 5)], [m("div", {key: 6}, 6)]])) m.render(root, m("div", [m("div", 1), m("div", 2), [m("div", {key: 3}, 3), m("div", {key: 4}, 4), m("div", {key:5}, 5)], [m("div", {key: 6}, 6)]]))
m.render(root, m("div", [m("div", 1), null, [m("div", {key: 3}, 3), m("div", {key: 4}, 4), m("div", {key:5}, 5)], [m("div", {key: 6}, 6)]])) m.render(root, m("div", [m("div", 1), null, [m("div", {key: 3}, 3), m("div", {key: 4}, 4), m("div", {key:5}, 5)], [m("div", {key: 6}, 6)]]))
return root.childNodes[0].childNodes.map(function(c) {return c.childNodes ? c.childNodes[0].nodeValue: c.nodeValue}).slice(0, 5).join("") == "13456" return root.childNodes[0].childNodes.map(function(c) {return c.childNodes ? c.childNodes[0].nodeValue: c.nodeValue}).join("") == "13456"
}) })
test(function() { test(function() {
var root = mock.document.createElement("div") var root = mock.document.createElement("div")
@ -1749,6 +1749,57 @@ function testMithril(mock) {
m.render(root, m("div", "test")) m.render(root, m("div", "test"))
return root.childNodes[0].childNodes.length == 1 return root.childNodes[0].childNodes.length == 1
}) })
test(function() {
//if an element is preceded by a conditional, it should not lose its identity
var root = mock.document.createElement("div")
m.render(root, m("div", [m("a"), m("input[autofocus]")]))
var before = root.childNodes[0].childNodes[1]
m.render(root, m("div", [undefined, m("input[autofocus]")]))
var after = root.childNodes[0].childNodes[1]
return before === after
})
test(function() {
//unkeyed element should maintain identity if mixed w/ keyed elements and identity can be inferred
var root = mock.document.createElement("div")
m.render(root, m("div", [m("a", {key: 1}), m("a", {key: 2}), m("a", {key: 3}), m("i")]))
var before = root.childNodes[0].childNodes[3]
m.render(root, m("div", [m("b", {key: 3}), m("b", {key: 4}), m("i"), m("b", {key: 1})]))
var after = root.childNodes[0].childNodes[2]
return before === after
})
test(function() {
//unkeyed element should maintain identity if mixed w/ keyed elements and text nodes and identity can be inferred
var root = mock.document.createElement("div")
m.render(root, m("div", [m("a", {key: 1}), m("a", {key: 2}), "foo", m("a", {key: 3}), m("i")]))
var before = root.childNodes[0].childNodes[4]
m.render(root, m("div", [m("a", {key: 3}), m("a", {key: 4}), "bar", m("i"), m("a", {key: 1})]))
var after = root.childNodes[0].childNodes[3]
return before === after
})
test(function() {
var root = mock.document.createElement("div")
m.render(root, m("div", [m("a", {key: 1}), m("a", {key: 2}), null, m("a", {key: 3}), m("i")]))
var before = root.childNodes[0].childNodes[4]
m.render(root, m("div", [m("a", {key: 3}), m("a", {key: 4}), null, m("i"), m("a", {key: 1})]))
var after = root.childNodes[0].childNodes[3]
return before === after
})
test(function() {
var root = mock.document.createElement("div")
m.render(root, m("div", [m("a", {key: 1}), m("a", {key: 2}), undefined, m("a", {key: 3}), m("i")]))
var before = root.childNodes[0].childNodes[4]
m.render(root, m("div", [m("a", {key: 3}), m("a", {key: 4}), undefined, m("i"), m("a", {key: 1})]))
var after = root.childNodes[0].childNodes[3]
return before === after
})
test(function() {
var root = mock.document.createElement("div")
m.render(root, m("div", [m("a", {key: 1}), m("a", {key: 2}), m.trust("a"), m("a", {key: 3}), m("i")]))
var before = root.childNodes[0].childNodes[4]
m.render(root, m("div", [m("a", {key: 3}), m("a", {key: 4}), m.trust("a"), m("i"), m("a", {key: 1})]))
var after = root.childNodes[0].childNodes[3]
return before === after
})
//end m.render //end m.render
//m.redraw //m.redraw