diff --git a/archive/v0.1.11/change-log.html b/archive/v0.1.11/change-log.html index 2e129612..ff3d3053 100644 --- a/archive/v0.1.11/change-log.html +++ b/archive/v0.1.11/change-log.html @@ -62,6 +62,12 @@
v0.1.11 - maintenance
+m.route() overload to allow reading of current route #61v0.1.10 - maintenance
In addition to bi-directional data binding, we can also bind parameterized functions to events:
m("button", {onclick: ctrl.add.bind(ctrl, ctrl.description)}, "Add")
-In the code above, we are simply using the native Javascript Function::bind method. This creates a new function with the parameter already set. In functional programming, this is called currying.
In the code above, we are simply using the native Javascript Function::bind method. This creates a new function with the parameter already set. In functional programming, this is called partial application.
The ctrl.add.bind(ctrl, ctrl.description) expression above returns a function that is equivalent to this code:
onclick: function(e) {
ctrl.add(ctrl.description)
@@ -262,7 +262,7 @@ m("table", [
- The template is rendered as a child of the implicit
<html> element of the document
- The text input saves its value to the
ctrl.description getter-setter we defined earlier
-The button calls the ctrl.add method when clicked. The .bind(ctrl, ctrl.description) idiom is a functional curry.
+The button calls the ctrl.add method when clicked. The .bind(ctrl, ctrl.description) idiom is a partial application.
In this example, it's only used to maintain the scope binding for the this parameter in the controller method, but typically it's also used to bind parameters to the function without the need to declare a wrapper anonymous function.
- The table lists all the existing to-dos, if any.
@@ -409,7 +409,7 @@ this.description = function(value) {
Another feature - the optional m() utility - allows writing terse templates in a declarative style using CSS shorthands, similar to popular HTML preprocessors from server-side MVC frameworks.
And because Mithril views are javascript, the developer has full freedom to abstract common patterns - from bidirectional binding helpers to full blown components - using standard javascript refactoring techniques.
Mithril templates are also more collision-proof than other component systems since there's no way to pollute the HTML tag namespace by defining ad-hoc tag names.
-A more intellectually interesting aspect of the framework is that event handling is encouraged to be done via functional composition (i.e. by using tools like m.withAttr, m.prop and the native .bind() method for currying).
+A more intellectually interesting aspect of the framework is that event handling is encouraged to be done via functional composition (i.e. by using tools like m.withAttr, m.prop and the native .bind() method for partial application).
If you've been interested in learning or using Functional Programming in the real world, Mithril provides very pragmatic opportunities to get into it.
Learn More
diff --git a/archive/v0.1.11/mithril-tests.js b/archive/v0.1.11/mithril-tests.js
index ce5d7676..7c8182da 100644
--- a/archive/v0.1.11/mithril-tests.js
+++ b/archive/v0.1.11/mithril-tests.js
@@ -398,6 +398,9 @@ Mithril = m = new function app(window) {
xhr.open(options.method, options.url, true, options.user, options.password)
xhr.onload = typeof options.onload == "function" ? options.onload : function() {}
xhr.onerror = typeof options.onerror == "function" ? options.onerror : function() {}
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState === 4 && xhr.status === 0) xhr.onerror({type: "error", target: xhr})
+ }
if (typeof options.config == "function") options.config(xhr, options)
xhr.send(options.data)
return xhr
@@ -1012,6 +1015,24 @@ function testMithril(mock) {
var paramValueAfter = m.route.param("a1")
return mock.location.search == "?/" && paramValueBefore === "foo" && paramValueAfter === undefined
})
+ test(function() {
+ //https://github.com/lhorie/mithril.js/issues/61
+ mock.performance.$elapse(50)
+ mock.location.search = "?"
+
+ var module = {controller: function() {}, view: function() {return m.route.param("a1")}}
+
+ var root = mock.document.createElement("div")
+ m.route.mode = "search"
+ m.route(root, "/test7/foo", {
+ "/": module,
+ "/test7/:a1": module
+ })
+ var routeValueBefore = m.route()
+ m.route("/")
+ var routeValueAfter = m.route()
+ return routeValueBefore === "/test7/foo" && routeValueAfter === "/"
+ })
//m.prop
test(function() {
diff --git a/archive/v0.1.11/mithril.js b/archive/v0.1.11/mithril.js
index 50ffbe9d..f7faa3fb 100644
--- a/archive/v0.1.11/mithril.js
+++ b/archive/v0.1.11/mithril.js
@@ -398,6 +398,9 @@ Mithril = m = new function app(window) {
xhr.open(options.method, options.url, true, options.user, options.password)
xhr.onload = typeof options.onload == "function" ? options.onload : function() {}
xhr.onerror = typeof options.onerror == "function" ? options.onerror : function() {}
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState === 4 && xhr.status === 0) xhr.onerror({type: "error", target: xhr})
+ }
if (typeof options.config == "function") options.config(xhr, options)
xhr.send(options.data)
return xhr
diff --git a/archive/v0.1.11/mithril.min.js b/archive/v0.1.11/mithril.min.js
index 0b4be62b..7c792f34 100644
--- a/archive/v0.1.11/mithril.min.js
+++ b/archive/v0.1.11/mithril.min.js
@@ -4,5 +4,5 @@ http://github.com/lhorie/mithril.js
(c) Leo Horie
License: MIT
*/
-Mithril=m=new function(a){function b(){var a=arguments,b="[object Object]"==u.call(a[1]),c=b?a[1]:{},d="class"in c?"class":"className",e=t[a[0]];if(void 0===e){t[a[0]]=e={tag:"div",attrs:{}};for(var f,h=[];f=v.exec(a[0]);)if(""==f[1])e.tag=f[2];else if("#"==f[1])e.attrs.id=f[2];else if("."==f[1])h.push(f[2]);else if("["==f[3][0]){var i=w.exec(f[3]);e.attrs[i[1]]=i[3]||!0}h.length>0&&(e.attrs[d]=h.join(" "))}e=g(e),e.attrs=g(e.attrs),e.children=b?a[2]:a[1];for(var j in c)e.attrs[j]=j==d?(e.attrs[j]||"")+" "+c[j]:c[j];return e}function c(b,g,h,i,j,k,l){if(null===h||void 0===h)return void(i&&e(i.nodes));if("retain"!==h.subtree){var m=u.call(i),n=u.call(h);if(m!=n&&(null!==i&&void 0!==i&&e(i.nodes),i=new h.constructor,i.nodes=[]),"[object Array]"==n){for(var o=[],p=i.length===h.length,q=0,r=0,s=0;r-1?new h.constructor(h):h,i.nodes=[v];else if(i.valueOf()!==h.valueOf()||j===!0){if(h.$trusted){var x=i.nodes[0],o=[x];if(x){for(;x=x.nextSibling;)o.push(x);e(o),v=f(b,k,h)}else b.innerHTML=h}else v=i.nodes[0],"textarea"===g?b.value=h:b.insertBefore(v,b.childNodes[k]||null),v.nodeValue=h;i=new h.constructor(h),i.nodes=[v]}else i.nodes.intact=!0}return i}}function d(b,c,d,e,f){for(var g in d){var i=d[g],j=e[g];if(!(g in e)||j!==i||b===a.document.activeElement){if(e[g]=i,"config"===g)continue;if("function"==typeof i&&0==g.indexOf("on"))b[g]=h(i,b);else if("style"===g)for(var k in i)(void 0===j||j[k]!==i[k])&&(b.style[k]=i[k]);else void 0!==f?"href"===g?b.setAttributeNS("http://www.w3.org/1999/xlink","href",i):"className"===g?b.setAttribute("class",i):b.setAttribute(g,i):"value"===g&&"input"===c?b.value!==i&&(b.value=i):g in b?b[g]=i:b.setAttribute(g,i)}}return e}function e(a){for(var b=0;b16)b.redraw();else{var c=a.cancelAnimationFrame||a.clearTimeout,d=a.requestAnimationFrame||a.setTimeout;c(F),F=d(b.redraw,0)}}function j(a,c,d){L={};for(var e in c){if(e==d)return!void b.module(a,c[e]);var f=new RegExp("^"+e.replace(/:[^\/]+/g,"([^\\/]+)")+"$");if(f.test(d))return!void d.replace(f,function(){for(var d=e.match(/:[^\/]+/g),f=[].slice.call(arguments,1,-2),g=0;g0&&("GET"==a.method?a.url=a.url+(a.url.indexOf("?")<0?"?":"&")+o(b):a.data=c(b)),a}function q(a,b){var c=a.match(/:[a-z]\w+/gi);if(c&&b)for(var d=0;de?y.push(b)-1:e,g=b==a.document||b==a.document.documentElement?x:b;z[f]=c(g,null,d,z[f],!1,0)},b.trust=function(a){return a=new String(a),a.$trusted=!0,a};var A=[],B=[],C=[],D=0,E=0,F=0;b.module=function(a,c){b.startComputation();var d=A.indexOf(a);0>d&&(d=A.length),A[d]=a,B[d]=c,C[d]=new c.controller,b.endComputation()},b.redraw=function(){for(var a=0;a0&&(e.attrs[d]=h.join(" "))}e=g(e),e.attrs=g(e.attrs),e.children=b?a[2]:a[1];for(var j in c)e.attrs[j]=j==d?(e.attrs[j]||"")+" "+c[j]:c[j];return e}function c(b,g,h,i,j,k,l){if(null===h||void 0===h)return void(i&&e(i.nodes));if("retain"!==h.subtree){var m=u.call(i),n=u.call(h);if(m!=n&&(null!==i&&void 0!==i&&e(i.nodes),i=new h.constructor,i.nodes=[]),"[object Array]"==n){for(var o=[],p=i.length===h.length,q=0,r=0,s=0;r-1?new h.constructor(h):h,i.nodes=[v];else if(i.valueOf()!==h.valueOf()||j===!0){if(h.$trusted){var x=i.nodes[0],o=[x];if(x){for(;x=x.nextSibling;)o.push(x);e(o),v=f(b,k,h)}else b.innerHTML=h}else v=i.nodes[0],"textarea"===g?b.value=h:b.insertBefore(v,b.childNodes[k]||null),v.nodeValue=h;i=new h.constructor(h),i.nodes=[v]}else i.nodes.intact=!0}return i}}function d(b,c,d,e,f){for(var g in d){var i=d[g],j=e[g];if(!(g in e)||j!==i||b===a.document.activeElement){if(e[g]=i,"config"===g)continue;if("function"==typeof i&&0==g.indexOf("on"))b[g]=h(i,b);else if("style"===g)for(var k in i)(void 0===j||j[k]!==i[k])&&(b.style[k]=i[k]);else void 0!==f?"href"===g?b.setAttributeNS("http://www.w3.org/1999/xlink","href",i):"className"===g?b.setAttribute("class",i):b.setAttribute(g,i):"value"===g&&"input"===c?b.value!==i&&(b.value=i):g in b?b[g]=i:b.setAttribute(g,i)}}return e}function e(a){for(var b=0;b16)b.redraw();else{var c=a.cancelAnimationFrame||a.clearTimeout,d=a.requestAnimationFrame||a.setTimeout;c(F),F=d(b.redraw,0)}}function j(a,c,d){L={};for(var e in c){if(e==d)return!void b.module(a,c[e]);var f=new RegExp("^"+e.replace(/:[^\/]+/g,"([^\\/]+)")+"$");if(f.test(d))return!void d.replace(f,function(){for(var d=e.match(/:[^\/]+/g),f=[].slice.call(arguments,1,-2),g=0;g0&&("GET"==a.method?a.url=a.url+(a.url.indexOf("?")<0?"?":"&")+o(b):a.data=c(b)),a}function q(a,b){var c=a.match(/:[a-z]\w+/gi);if(c&&b)for(var d=0;de?y.push(b)-1:e,g=b==a.document||b==a.document.documentElement?x:b;z[f]=c(g,null,d,z[f],!1,0)},b.trust=function(a){return a=new String(a),a.$trusted=!0,a};var A=[],B=[],C=[],D=0,E=0,F=0;b.module=function(a,c){b.startComputation();var d=A.indexOf(a);0>d&&(d=A.length),A[d]=a,B[d]=c,C[d]=new c.controller,b.endComputation()},b.redraw=function(){for(var a=0;a
The config option can also be used to retrieve the XMLHttpRequest instance for aborting the request. This idiom can also be used to attach onprogress event handlers.
var transport = m.prop();
+
+m.request({method: "POST", url: "/foo", config: transport});
+
+//the `transport` getter-setter contains an instance of XMLHttpRequest
+transport().abort();
+Promise request(XHROptions options)
@@ -277,7 +286,7 @@ where:
Data to be sent. It's automatically placed in the appropriate section of the request with the appropriate serialization based on method
any unwrapSuccess(any data) (optional)
-A preprocessor function to extract the data from a success response in case the response contains metadata wrapping the data.
+A preprocessor function to unwrap the data from a success response in case the response contains metadata wrapping the data.
The default value (if this parameter is falsy) is the identity function function(value) {return value}
For example, if the response is {data: [{name: "John"}, {name: "Mary"}]} and the unwrap function is function(response) {return response.data}, then the response will be considered to be [{name: "John"}, {name: "Mary"}] when processing the type parameter
@@ -290,7 +299,7 @@ where:
any unwrapError(any data) (optional)
-A preprocessor function to extract the data from an error response in case the response contains metadata wrapping the data.
+A preprocessor function to unwrap the data from an error response in case the response contains metadata wrapping the data.
The default value (if this parameter is falsy) is the identity function function(value) {return value}
Object | Array data
@@ -325,7 +334,7 @@ where:
any extract(XMLHttpRequest xhr, XHROptions options) (optional)
Method to use to extract the data from the raw XMLHttpRequest. This is useful when the relevant data is either in a response header or the status field.
-If this parameter is falsy, the default value is function(xhr, options) {return xhr.responseText}.
+If this parameter is falsy, the default value is a function that returns xhr.responseText.
void type(Object data) (optional)
The response object (or the child items if this object is an Array) will be passed as a parameter to the class constructor defined by type
diff --git a/docs/mithril.request.md b/docs/mithril.request.md
index 12ed8a05..4f51895e 100644
--- a/docs/mithril.request.md
+++ b/docs/mithril.request.md
@@ -259,6 +259,21 @@ m.request({method: "POST", url: "/foo", config: xhrConfig});
---
+### Aborting a request
+
+The `config` option can also be used to retrieve the `XMLHttpRequest` instance for aborting the request. This idiom can also be used to attach `onprogress` event handlers.
+
+```javascript
+var transport = m.prop();
+
+m.request({method: "POST", url: "/foo", config: transport});
+
+//the `transport` getter-setter contains an instance of XMLHttpRequest
+transport().abort();
+```
+
+---
+
### Signature
[How to read signatures](how-to-read-signatures.md)
@@ -315,7 +330,7 @@ where:
- **any unwrapSuccess(any data)** (optional)
- A preprocessor function to extract the data from a success response in case the response contains metadata wrapping the data.
+ A preprocessor function to unwrap the data from a success response in case the response contains metadata wrapping the data.
The default value (if this parameter is falsy) is the identity function `function(value) {return value}`
@@ -331,7 +346,7 @@ where:
- **any unwrapError(any data)** (optional)
- A preprocessor function to extract the data from an error response in case the response contains metadata wrapping the data.
+ A preprocessor function to unwrap the data from an error response in case the response contains metadata wrapping the data.
The default value (if this parameter is falsy) is the identity function `function(value) {return value}`
@@ -371,7 +386,7 @@ where:
Method to use to extract the data from the raw XMLHttpRequest. This is useful when the relevant data is either in a response header or the status field.
- If this parameter is falsy, the default value is `function(xhr, options) {return xhr.responseText}`.
+ If this parameter is falsy, the default value is a function that returns `xhr.responseText`.
- **void type(Object data)** (optional)
@@ -398,7 +413,7 @@ where:
The XMLHttpRequest instance.
- **XHROptions options**
-
+
The `options` parameter that was passed into `m.request` call
- **returns Promise promise**
diff --git a/mithril.js b/mithril.js
index 50ffbe9d..f7faa3fb 100644
--- a/mithril.js
+++ b/mithril.js
@@ -398,6 +398,9 @@ Mithril = m = new function app(window) {
xhr.open(options.method, options.url, true, options.user, options.password)
xhr.onload = typeof options.onload == "function" ? options.onload : function() {}
xhr.onerror = typeof options.onerror == "function" ? options.onerror : function() {}
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState === 4 && xhr.status === 0) xhr.onerror({type: "error", target: xhr})
+ }
if (typeof options.config == "function") options.config(xhr, options)
xhr.send(options.data)
return xhr