From e1b326d1a99b4f69b02e07a471dbbecb919e02dd Mon Sep 17 00:00:00 2001 From: Miles Matthias Date: Mon, 30 Mar 2015 16:35:06 -0600 Subject: [PATCH 1/2] added a link for the example app in jsfiddle for people. --- docs/getting-started.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/getting-started.md b/docs/getting-started.md index 9654f8f2..455833fb 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -447,6 +447,8 @@ m.module(document, todo); --- +This example is also available as a [jsFiddle](http://jsfiddle.net/milesmatthias/fbgypzbr/1/). + ## Notes on Architecture Let's look at each MVC layer in detail to illustrate some of Mithril's design principles and philosophies: From b111d058bea8dd3041d341a57e7cb2a1c14bf8eb Mon Sep 17 00:00:00 2001 From: Leo Horie Date: Tue, 31 Mar 2015 10:50:19 -0400 Subject: [PATCH 2/2] fix regression caused by #524 --- mithril.js | 17 ++++------ tests/mithril-tests.js | 73 +++++++++++++++++++++++++++++++++++------- 2 files changed, 68 insertions(+), 22 deletions(-) diff --git a/mithril.js b/mithril.js index 614c54a4..dba0bd6e 100644 --- a/mithril.js +++ b/mithril.js @@ -129,7 +129,6 @@ var m = (function app(window, undefined) { //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 //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 existing = {}, unkeyed = [], shouldMaintainIdentities = false; 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 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) { @@ -169,7 +171,6 @@ var m = (function app(window, undefined) { element: cached.nodes[existing[key].index] || $document.createElement("div") } } - else unkeyed.push({index: i, element: parentElement.childNodes[i] || $document.createElement("div")}) } } var actions = [] @@ -199,12 +200,6 @@ var m = (function app(window, undefined) { 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; } } diff --git a/tests/mithril-tests.js b/tests/mithril-tests.js index 837c3087..b90cef07 100644 --- a/tests/mithril-tests.js +++ b/tests/mithril-tests.js @@ -245,7 +245,7 @@ function testMithril(mock) { test(function() { var root = mock.document.createElement("div") m.render(root, m("div", [undefined])) - return root.childNodes[0].childNodes.length === 0 + return root.childNodes[0].childNodes[0].nodeValue == "" }) test(function() { var root = mock.document.createElement("div") @@ -268,19 +268,19 @@ function testMithril(mock) { var root = mock.document.createElement("div") m.render(root, m("ul", [m("li")])) m.render(root, m("ul", [m("li"), undefined])) - return root.childNodes[0].childNodes.length == 1 + return root.childNodes[0].childNodes[1].nodeValue == "" }) test(function() { var root = mock.document.createElement("div") m.render(root, m("ul", [m("li"), m("li")])) m.render(root, m("ul", [m("li"), undefined])) - return root.childNodes[0].childNodes.length == 1 + return root.childNodes[0].childNodes[1].nodeValue == "" }) test(function() { var root = mock.document.createElement("div") m.render(root, m("ul", [m("li")])) m.render(root, m("ul", [undefined])) - return root.childNodes[0].childNodes.length == 0 + return root.childNodes[0].childNodes[0].nodeValue == "" }) test(function() { var root = mock.document.createElement("div") @@ -463,18 +463,18 @@ function testMithril(mock) { m.render(root, m("div", [m("button"), m("ul")])) var valueBefore = root.childNodes[0].childNodes[0].nodeName m.render(root, m("div", [undefined, m("ul")])) - var valueAfter = root.childNodes[0].childNodes[0].nodeName - return valueBefore === "BUTTON" && valueAfter === "UL" + var valueAfter = root.childNodes[0].childNodes[0].nodeValue + return valueBefore === "BUTTON" && valueAfter === "" }) test(function() { var root = mock.document.createElement("div") m.render(root, m("div", [m("ul"), undefined])) 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")])) - var valueAfter1 = root.childNodes[0].childNodes[0].nodeName - var valueAfter2 = root.childNodes[0].childNodes.length - return valueBefore1 === "UL" && valueAfter1 === "UL" && valueBefore2 === 1 && valueAfter2 === 1 + var valueAfter1 = root.childNodes[0].childNodes[0].nodeValue + var valueAfter2 = root.childNodes[0].childNodes[1].nodeName + return valueBefore1 === "UL" && valueAfter1 === "" && valueBefore2 === "" && valueAfter2 === "UL" }) test(function() { //https://github.com/lhorie/mithril.js/issues/79 @@ -916,7 +916,7 @@ function testMithril(mock) { 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), 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() { var root = mock.document.createElement("div") @@ -949,6 +949,57 @@ function testMithril(mock) { m.render(root, m("div", "test")) 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 //m.redraw