From 40251c6c16f29473d3ab0ecbad4293978d9b073c Mon Sep 17 00:00:00 2001 From: Leo Horie Date: Tue, 4 Oct 2016 12:19:55 -0400 Subject: [PATCH] #1342 update m.route.link target if href changes --- mithril.js | 4 +- mithril.min.js | 84 +++++++++++++++--------------- router/router.js | 4 +- router/tests/index.html | 4 ++ router/tests/test-link.js | 87 ++++++++++++++++++++++++++++++++ test-utils/domMock.js | 5 ++ test-utils/tests/test-domMock.js | 9 ++++ 7 files changed, 153 insertions(+), 44 deletions(-) create mode 100644 router/tests/test-link.js diff --git a/mithril.js b/mithril.js index 5d66f1ae..b32feeef 100644 --- a/mithril.js +++ b/mithril.js @@ -1123,7 +1123,9 @@ var coreRouter = function($window) { vnode2.dom.onclick = function(e) { e.preventDefault() e.redraw = false - setPath(vnode2.attrs.href, undefined, undefined) + var href = this.getAttribute("href") + if (href.indexOf(prefix1) === 0) href = href.slice(prefix1.length) + setPath(href, undefined, undefined) } } return {setPrefix: setPrefix, getPath: getPath, setPath: setPath, defineRoutes: defineRoutes, link: link} diff --git a/mithril.min.js b/mithril.min.js index 6475ad96..e7525777 100644 --- a/mithril.min.js +++ b/mithril.min.js @@ -1,42 +1,42 @@ -new function(){function u(b,e,l,g,k,h){return{tag:b,key:e,attrs:l,children:g,text:k,dom:h,domSize:void 0,state:{},events:void 0,instance:void 0,skip:!1}}function w(b){if(null==b||"string"!==typeof b&&null==b.view)throw Error("The selector must be either a string or a component.");if("string"===typeof b&&void 0===G[b]){for(var e,l,g=[],k={};e=P.exec(b);){var h=e[1],q=e[2];""===h&&""!==q?l=q:"#"===h?k.id=q:"."===h?g.push(q):"["===e[3][0]&&((h=e[6])&&(h=h.replace(/\\(["'])/g,"$1").replace(/\\\\/g,"\\")), -k[e[4]]=h||!0)}0d.filter(E).length)throw Error("Ensure that each item passed to m.prop.combine/m.prop.merge is a stream");return x(e(),d,function(){var b= -d.filter(M);if(0b.indexOf("?")?"?":"&";b+=h+g}return b}function k(b){try{return""!==b?JSON.parse(b):null}catch(e){throw Error(b);}}function h(b){return b.responseText}function q(b,e){if("function"===typeof b)if(e instanceof Array)for(var g=0;gm.status||304=== -m.status)p(q(f.type,b));else{var e=Error(m.responseText),g;for(g in b)e[g]=b[g];p.error(e)}}catch(k){p.error(k)}"function"===typeof r&&r()}};A?m.send(f.data):m.send();return p},jsonp:function(f){var h=e();void 0!==f.initialValue&&h(f.initialValue);var k=f.callbackName||"_mithril_"+Math.round(1E16*Math.random())+"_"+t++,m=b.document.createElement("script");b[k]=function(e){m.parentNode.removeChild(m);h(q(f.type,e));"function"===typeof r&&r();delete b[k]};m.onerror=function(){m.parentNode.removeChild(m); -h.error(Error("JSONP request failed"));"function"===typeof r&&r();delete b[k]};null==f.data&&(f.data={});f.url=l(f.url,f.data);f.data[f.callbackKey||"callback"]=k;m.src=g(f.url,f.data);b.document.documentElement.appendChild(m);return h},setCompletionCallback:function(b){r=b}}}(window,N),J=function(){var b=[];return{subscribe:b.push.bind(b),unsubscribe:function(e){e=b.indexOf(e);-1=v&&A>=m;){var y=a[v],n=d[m];if(y===n)v++,m++;else if(null!=y&&null!=n&&y.key===n.key)v++,m++,h(c,y,n,b,t(a,v,g),p,k),p&&y.tag===n.tag&&r(c,q(y),g);else if(y=a[x],y===n)x--,m++;else if(null!=y&&null!=n&&y.key===n.key)h(c,y,n,b,t(a,x+1,g),p,k),m=v&&A>=m;){y=a[x];n=d[A];if(y===n)x--;else if(null!=y&&null!=n&&y.key===n.key)h(c,y,n,b,t(a,x+1,g),p,k),p&&y.tag===n.tag&&r(c,q(y),g),null!=y.dom&&(g=y.dom),x--;else{if(!B){B=a;var y=x,u={},w;for(w=0;w< -y;w++){var C=B[w];null!=C&&(C=C.key,null!=C&&(u[C]=w))}B=u}null!=n&&(y=B[n.key],null!=y?(u=a[y],h(c,u,n,b,t(a,x+1,g),p,k),r(c,q(u),g),a[y].skip=!0,null!=u.dom&&(g=u.dom)):(n=l(n,b,void 0),r(c,n,g),g=n))}A--;if(Ad.filter(D).length)throw Error("Ensure that each item passed to m.prop.combine/m.prop.merge is a stream");return w(e(),d,function(){var b= +d.filter(L);if(0b.indexOf("?")?"?":"&";b+=h+g}return b}function k(b){try{return""!==b?JSON.parse(b):null}catch(e){throw Error(b);}}function h(b){return b.responseText}function q(b,e){if("function"===typeof b)if(e instanceof Array)for(var g=0;gn.status||304=== +n.status)l(q(f.type,b));else{var e=Error(n.responseText),g;for(g in b)e[g]=b[g];l.error(e)}}catch(k){l.error(k)}"function"===typeof r&&r()}};A?n.send(f.data):n.send();return l},jsonp:function(f){var h=e();void 0!==f.initialValue&&h(f.initialValue);var k=f.callbackName||"_mithril_"+Math.round(1E16*Math.random())+"_"+t++,n=b.document.createElement("script");b[k]=function(e){n.parentNode.removeChild(n);h(q(f.type,e));"function"===typeof r&&r();delete b[k]};n.onerror=function(){n.parentNode.removeChild(n); +h.error(Error("JSONP request failed"));"function"===typeof r&&r();delete b[k]};null==f.data&&(f.data={});f.url=m(f.url,f.data);f.data[f.callbackKey||"callback"]=k;n.src=g(f.url,f.data);b.document.documentElement.appendChild(n);return h},setCompletionCallback:function(b){r=b}}}(window,M),I=function(){var b=[];return{subscribe:b.push.bind(b),unsubscribe:function(e){e=b.indexOf(e);-1=l&&A>=n;){var x=a[l],p=d[n];if(x===p)l++,n++;else if(null!=x&&null!=p&&x.key===p.key)l++,n++,h(c,x,p,b,t(a,l,g),z,k),z&&x.tag===p.tag&&r(c,q(x),g);else if(x=a[w],x===p)w--,n++;else if(null!=x&&null!=p&&x.key===p.key)h(c,x,p,b,t(a,w+1,g),z,k),n=l&&A>=n;){x=a[w];p=d[A];if(x===p)w--;else if(null!=x&&null!=p&&x.key===p.key)h(c,x,p,b,t(a,w+1,g),z,k),z&&x.tag===p.tag&&r(c,q(x),g),null!=x.dom&&(g=x.dom),w--;else{if(!B){B=a;var x=w,u={},v;for(v=0;v< +x;v++){var C=B[v];null!=C&&(C=C.key,null!=C&&(u[C]=v))}B=u}null!=p&&(x=B[p.key],null!=x?(u=a[x],h(c,u,p,b,t(a,w+1,g),z,k),r(c,q(u),g),a[x].skip=!0,null!=u.dom&&(g=u.dom)):(p=m(p,b,void 0),r(c,p,g),g=p))}A--;if(A + + + + diff --git a/router/tests/test-link.js b/router/tests/test-link.js new file mode 100644 index 00000000..3d07af2e --- /dev/null +++ b/router/tests/test-link.js @@ -0,0 +1,87 @@ +"use strict" + +var o = require("../../ospec/ospec") +var renderService = require("../../render/render") +var callAsync = require("../../test-utils/callAsync") +var pushStateMock = require("../../test-utils/pushStateMock") +var domMock = require("../../test-utils/domMock") +var Router = require("../../router/router") + +o.spec("Router.link", function() { + void [{protocol: "http:", hostname: "localhost"}, {protocol: "file:", hostname: "/"}].forEach(function(env) { + void ["#", "?", "", "#!", "?!", "/foo"].forEach(function(prefix) { + o.spec("using prefix `" + prefix + "` starting on " + env.protocol + "//" + env.hostname, function() { + var $window, dom, root, router, onRouteChange, onFail, render + + o.beforeEach(function() { + $window = pushStateMock(env) + dom = domMock() + root = dom.document.body + router = new Router($window) + router.setPrefix(prefix) + onRouteChange = o.spy() + onFail = o.spy() + render = renderService(dom).render + }) + + o("works", function(done) { + var A = { + view: function() { + return {tag: "a", attrs: {href: "/b", oncreate: router.link}} + } + } + var B = { + view: function() { + return {tag: "a", attrs: {href: "/a", oncreate: router.link}} + } + } + + $window.location.href = prefix + "/a" + router.defineRoutes({"/a": {tag: A}, "/b": {tag: B}}, function(component) { + render(root, component) + }) + + callAsync(function() { + var e = dom.document.createEvent("MouseEvents") + e.initEvent("click", true, true) + root.firstChild.dispatchEvent(e) + + callAsync(function() { + o(router.getPath()).equals("/b") + + done() + }) + }) + }) + + o("works after update", function(done) { + var id = "a" + var A = { + view: function() { + return {tag: "a", attrs: {href: "/" + id, oncreate: router.link}} + } + } + + $window.location.href = prefix + "/a" + router.defineRoutes({"/a": {tag: A}, "/b": {tag: A}}, function(component) { + render(root, {tag: A}) + id = "b" + render(root, {tag: A}) + }) + + callAsync(function() { + var e = dom.document.createEvent("MouseEvents") + e.initEvent("click", true, true) + root.firstChild.dispatchEvent(e) + + callAsync(function() { + o(router.getPath()).equals("/b") + + done() + }) + }) + }) + }) + }) + }) +}) diff --git a/test-utils/domMock.js b/test-utils/domMock.js index d82118da..1e78f070 100644 --- a/test-utils/domMock.js +++ b/test-utils/domMock.js @@ -60,6 +60,10 @@ module.exports = function() { } } } + function getAttribute(name) { + if (this.attributes[name] == null) return null + return this.attributes[name].nodeValue + } function setAttribute(name, value) { var nodeValue = String(value) this.attributes[name] = { @@ -146,6 +150,7 @@ module.exports = function() { appendChild: appendChild, removeChild: removeChild, insertBefore: insertBefore, + getAttribute: getAttribute, setAttribute: setAttribute, setAttributeNS: setAttributeNS, removeAttribute: removeAttribute, diff --git a/test-utils/tests/test-domMock.js b/test-utils/tests/test-domMock.js index fbdcc0b9..bbc898b2 100644 --- a/test-utils/tests/test-domMock.js +++ b/test-utils/tests/test-domMock.js @@ -313,6 +313,15 @@ o.spec("domMock", function() { }) }) + o.spec("getAttribute", function() { + o("works", function() { + var div = $document.createElement("div") + div.setAttribute("id", "aaa") + + o(div.getAttribute("id")).equals("aaa") + }) + }) + o.spec("setAttribute", function() { o("works", function() { var div = $document.createElement("div")