From 1e9ddc637ee8845565ff9d88e8a1a24744dc1166 Mon Sep 17 00:00:00 2001 From: Leo Horie Date: Mon, 30 Mar 2015 09:23:50 -0400 Subject: [PATCH 1/4] #519 fix links --- docs/mithril.render.md | 2 +- docs/mithril.request.md | 12 +++++++----- docs/mithril.route.md | 4 ++-- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/mithril.render.md b/docs/mithril.render.md index a391156c..c887cff5 100644 --- a/docs/mithril.render.md +++ b/docs/mithril.render.md @@ -3,7 +3,7 @@ --- - [Usage](#usage) -- [Subtree directives](#subtree directives) +- [Subtree directives](#subtree-directives) - [Signature](#signature) --- diff --git a/docs/mithril.request.md b/docs/mithril.request.md index 2b474861..e4b58c4c 100644 --- a/docs/mithril.request.md +++ b/docs/mithril.request.md @@ -10,7 +10,7 @@ - [Casting the Response Data to a Class](#casting-the-response-data-to-a-class) - [Unwrapping Response Data](#unwrapping-response-data) - [Using Different Data Transfer Formats](#using-different-data-transfer-formats) -- [File uploads with FormData](#file-uploads-with-form-data) +- [File uploads with FormData](#file-uploads-with-formdata) - [Using variable data formats](#using-variable-data-formats) - [Extracting Metadata from the Response](#extracting-metadata-from-the-response) - [Custom request rejections](#custom-request-rejections) @@ -168,7 +168,7 @@ var log = function(value) { } var users = m.request({method: "GET", url: "/user"}) - .then(log); + .then(log) .then(function(users) { //add one more user to the response return users.concat({name: "Jane"}) @@ -338,7 +338,7 @@ You can read more about the [promise exception monitor here](mithril.deferred.md The `config` option can be used to arbitrarily configure the native XMLHttpRequest instance and to access properties that would not be accessible otherwise. -The example below show how to configure a request where the server expects requests to have a `Content-Type: application/json` header +The example below shows how to configure a request where the server expects requests to have a `Content-Type: application/json` header ```javascript var xhrConfig = function(xhr) { @@ -477,9 +477,9 @@ where: Determines whether the `m.request` can affect template rendering. Defaults to false. - If this option is set to true, then the request does NOT call [`m.startComputation` / `m.endComputation`](mithril.computation.md), and therefore the completion of the request does not trigger an update of the view, even if data has been changed. This option is useful for running operations in the background (i.e. without user intervention). + If this option is set to true, then the request does NOT call [`m.startComputation` / `m.endComputation`](mithril.computation.md), and therefore the completion of the request does not trigger an update of the view, even if data has been changed. This option is useful for running operations in the background (i.e. without user intervention). It's strongly recommended that you set an `initialValue` option in ALL requests if you set the `background` option to true. - In order to force a redraw after a background request, use [`m.redraw`](mithril.redraw.md) + In order to force a redraw after a background request, use [`m.redraw`](mithril.redraw.md), or `m.startComputation` / `m.endComputation`. ```javascript var demo = {} @@ -508,6 +508,8 @@ where: The value that populates the returned getter-setter before the request completes. This is useful when using the `background` option, in order to avoid the need for null checks in views that may be attempting to access the returned getter-setter before the asynchronous request resolves. + It is strongly recommended that you always set this option to avoid future surprises. + - **any unwrapSuccess(any data, XMLHttpRequest xhr)** (optional) A preprocessor function to unwrap the data from a success response in case the response contains metadata wrapping the data. diff --git a/docs/mithril.route.md b/docs/mithril.route.md index a9305aa5..af9f9390 100644 --- a/docs/mithril.route.md +++ b/docs/mithril.route.md @@ -8,7 +8,7 @@ - [Running clean up code on route change](#running-clean-up-code-on-route-change) - [Redirecting](#redirecting) - [Reading the currently active route](#reading-the-currently-active-route) -- [Mode abstraction](#mode abstraction) +- [Mode abstraction](#mode-abstraction) --- @@ -78,7 +78,7 @@ This redirects to the URL `http://server/#/dashboard/johndoe` and yields: Above, `dashboard` is a module. It contains a `controller` and a `view` properties. When the URL matches a route, the respective module's controller is instantiated and passed as a parameter to the view. -In this case, since there's only route, the app redirects to the default route `"/dashboard/johndoe"`. +In this case, since there's only one route, the app redirects to the default route `"/dashboard/johndoe"`. The string `johndoe` is bound to the `:userID` parameter, which can be retrieved programmatically in the controller via `m.route.param("userID")`. From b6c2f705266d7ee2ff81b57d43c839670bd257f0 Mon Sep 17 00:00:00 2001 From: Leo Horie Date: Mon, 30 Mar 2015 10:55:34 -0400 Subject: [PATCH 2/4] add missing return --- docs/mithril.render.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/mithril.render.md b/docs/mithril.render.md index c887cff5..0b4c6beb 100644 --- a/docs/mithril.render.md +++ b/docs/mithril.render.md @@ -60,7 +60,7 @@ This mechanism is only intended to be used as a last resort optimization tool. I The example below shows how to use a SubtreeDirective object to create a static header that doesn't incur diff costs once it has been rendered. This means that we are avoiding the creation of the header subtree (and therefore skipping the diff algorithm) altogether, but it also means that dynamic variables will NOT be updated within the header. -``` +```javascript var app = {} //here's an example plugin that determines whether data has changes. @@ -78,7 +78,7 @@ app.bindOnce = (function() { //here's the view app.view = function() { - m(".layout", [ + return m(".layout", [ app.bindOnce(function() { //this only runs once in order to boost performance //dynamic variables are not updated here From 648f4734b51cea19738d350d3358871447ba4476 Mon Sep 17 00:00:00 2001 From: Leo Horie Date: Mon, 30 Mar 2015 13:25:32 -0400 Subject: [PATCH 3/4] #524 fix diff bug when mixing undefined in a tree --- mithril.js | 6 ++++-- tests/mithril-tests.js | 48 +++++++++++++++++++++++++++++++++--------- 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/mithril.js b/mithril.js index 4a1ad840..614c54a4 100644 --- a/mithril.js +++ b/mithril.js @@ -138,13 +138,15 @@ var m = (function app(window, undefined) { existing[cached[i].attrs.key] = {action: DELETION, index: i} } } + + 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 (shouldMaintainIdentities) { - if (data.indexOf(null) > -1) data = data.filter(function(x) {return x != null}) - var keysDiffer = false if (data.length != cached.length) keysDiffer = true else for (var i = 0, cachedCell, dataCell; cachedCell = cached[i], dataCell = data[i]; i++) { diff --git a/tests/mithril-tests.js b/tests/mithril-tests.js index 336bc8c6..76e0b9c4 100644 --- a/tests/mithril-tests.js +++ b/tests/mithril-tests.js @@ -43,6 +43,32 @@ function testMithril(mock) { test(function() {return m("div", [1], [2], [3]).children.length === 3}) //m.module + test(function() { + var root = mock.document.createElement("div") + var whatever = 1 + var app = { + view: function() { + return [ + whatever % 2 ? m('span', '% 2') : undefined, + m('div', 'bugs'), + m('a'), + ] + } + } + m.module(root, app) + mock.requestAnimationFrame.$resolve() + + whatever++ + m.redraw() + mock.requestAnimationFrame.$resolve() + + whatever++ + m.redraw() + mock.requestAnimationFrame.$resolve() + + return root.childNodes.length + }) + test(function() { mock.requestAnimationFrame.$resolve() @@ -219,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[0].nodeValue === "" + return root.childNodes[0].childNodes.length === 0 }) test(function() { var root = mock.document.createElement("div") @@ -242,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[1].nodeValue === "" + return root.childNodes[0].childNodes.length == 1 }) 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 == 2 && root.childNodes[0].childNodes[1].nodeValue === "" + return root.childNodes[0].childNodes.length == 1 }) 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[0].nodeValue === "" + return root.childNodes[0].childNodes.length == 0 }) test(function() { var root = mock.document.createElement("div") @@ -437,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].nodeValue - return valueBefore === "BUTTON" && valueAfter === "" + var valueAfter = root.childNodes[0].childNodes[0].nodeName + return valueBefore === "BUTTON" && valueAfter === "UL" }) 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[1].nodeValue + var valueBefore2 = root.childNodes[0].childNodes.length m.render(root, m("div", [undefined, m("ul")])) - var valueAfter1 = root.childNodes[0].childNodes[0].nodeValue - var valueAfter2 = root.childNodes[0].childNodes[1].nodeName - return valueBefore1 === "UL" && valueAfter1 === "" && valueBefore2 === "" && valueAfter2 === "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 }) test(function() { //https://github.com/lhorie/mithril.js/issues/79 @@ -2782,6 +2808,8 @@ function testMithril(mock) { } //mock +var start = performance.now() testMithril(mock.window); +console.log("test finished running in:", performance.now() - start, "ms") test.print(function(value) {console.log(value)}) From 8d9fa8ff04efc07020d9998a4f0764bb200766b3 Mon Sep 17 00:00:00 2001 From: Leo Horie Date: Mon, 30 Mar 2015 13:26:56 -0400 Subject: [PATCH 4/4] remove timing code --- tests/mithril-tests.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/mithril-tests.js b/tests/mithril-tests.js index 76e0b9c4..837c3087 100644 --- a/tests/mithril-tests.js +++ b/tests/mithril-tests.js @@ -2808,8 +2808,6 @@ function testMithril(mock) { } //mock -var start = performance.now() testMithril(mock.window); -console.log("test finished running in:", performance.now() - start, "ms") test.print(function(value) {console.log(value)})