Comparing version 1.0.0-rc.5 to 1.0.0-rc.6
"use strict" | ||
var Vnode = require("../render/vnode") | ||
var autoredraw = require("../api/autoredraw") | ||
module.exports = function(renderer, pubsub) { | ||
module.exports = function(redrawService) { | ||
return function(root, component) { | ||
if (component === null) { | ||
renderer.render(root, []) | ||
pubsub.unsubscribe(root.redraw) | ||
delete root.redraw | ||
redrawService.render(root, []) | ||
redrawService.unsubscribe(root) | ||
return | ||
@@ -16,9 +14,9 @@ } | ||
if (component.view == null) throw new Error("m.mount(element, component) expects a component, not a vnode") | ||
var run = autoredraw(root, renderer, pubsub, function() { | ||
renderer.render(root, Vnode(component, undefined, undefined, undefined, undefined, undefined)) | ||
}) | ||
run() | ||
var run = function() { | ||
redrawService.render(root, Vnode(component)) | ||
} | ||
redrawService.subscribe(root, run) | ||
redrawService.redraw() | ||
} | ||
} |
"use strict" | ||
var Vnode = require("../render/vnode") | ||
var Promise = require("../promise/promise") | ||
var coreRouter = require("../router/router") | ||
module.exports = function($window, mount) { | ||
var router = coreRouter($window) | ||
var currentResolve, currentComponent, currentRender, currentArgs, currentPath | ||
module.exports = function($window, redrawService) { | ||
var routeService = coreRouter($window) | ||
var RouteComponent = {view: function() { | ||
return [currentRender(Vnode(currentComponent, null, currentArgs, undefined, undefined, undefined))] | ||
}} | ||
function defaultRender(vnode) { | ||
return vnode | ||
} | ||
var identity = function(v) {return v} | ||
var render, component, attrs, currentPath, updatePending = false | ||
var route = function(root, defaultRoute, routes) { | ||
currentComponent = "div" | ||
currentRender = defaultRender | ||
currentArgs = null | ||
mount(root, RouteComponent) | ||
router.defineRoutes(routes, function(payload, args, path) { | ||
var isResolver = typeof payload.view !== "function" | ||
var render = defaultRender | ||
var resolve = currentResolve = function (component) { | ||
if (resolve !== currentResolve) return | ||
currentResolve = null | ||
currentComponent = component != null ? component : isResolver ? "div" : payload | ||
currentRender = render | ||
currentArgs = args | ||
currentPath = path | ||
root.redraw(true) | ||
if (root == null) throw new Error("Ensure the DOM element that was passed to `m.route` is not undefined") | ||
var update = function(routeResolver, comp, params, path) { | ||
component = comp != null && typeof comp.view === "function" ? comp : "div", attrs = params, currentPath = path, updatePending = false | ||
render = (routeResolver.render || identity).bind(routeResolver) | ||
run() | ||
} | ||
var run = function() { | ||
if (render != null) redrawService.render(root, render(Vnode(component, attrs.key, attrs))) | ||
} | ||
var bail = function() { | ||
routeService.setPath(defaultRoute) | ||
} | ||
routeService.defineRoutes(routes, function(payload, params, path) { | ||
if (payload.view) update({}, payload, params, path) | ||
else { | ||
if (payload.onmatch) { | ||
updatePending = true | ||
Promise.resolve(payload.onmatch(params, path)).then(function(resolved) { | ||
if (updatePending) update(payload, resolved, params, path) | ||
}, bail) | ||
} | ||
else update(payload, "div", params, path) | ||
} | ||
var onmatch = function() { | ||
resolve() | ||
} | ||
if (isResolver) { | ||
if (typeof payload.render === "function") render = payload.render.bind(payload) | ||
if (typeof payload.onmatch === "function") onmatch = payload.onmatch | ||
} | ||
onmatch.call(payload, resolve, args, path) | ||
}, function() { | ||
router.setPath(defaultRoute, null, {replace: true}) | ||
}) | ||
}, bail) | ||
redrawService.subscribe(root, run) | ||
} | ||
route.link = router.link | ||
route.prefix = router.setPrefix | ||
route.set = router.setPath | ||
route.set = function(path, data, options) { | ||
if (updatePending) options = {replace: true} | ||
updatePending = false | ||
routeService.setPath(path, data, options) | ||
} | ||
route.get = function() {return currentPath} | ||
route.prefix = function(prefix) {routeService.prefix = prefix} | ||
route.link = function(vnode) { | ||
vnode.dom.setAttribute("href", routeService.prefix + vnode.attrs.href) | ||
vnode.dom.onclick = function(e) { | ||
if (e.ctrlKey || e.metaKey || e.shiftKey || e.which === 2) return | ||
e.preventDefault() | ||
e.redraw = false | ||
var href = this.getAttribute("href") | ||
if (href.indexOf(routeService.prefix) === 0) href = href.slice(routeService.prefix.length) | ||
route.set(href, undefined, undefined) | ||
} | ||
} | ||
return route | ||
} |
@@ -8,3 +8,3 @@ "use strict" | ||
var coreRenderer = require("../../render/render") | ||
var apiPubSub = require("../../api/pubsub") | ||
var apiRedraw = require("../../api/redraw") | ||
var apiMounter = require("../../api/mount") | ||
@@ -14,3 +14,3 @@ | ||
var FRAME_BUDGET = Math.floor(1000 / 60) | ||
var $window, root, redraw, mount, render | ||
var $window, root, redrawService, mount, render | ||
@@ -22,4 +22,4 @@ o.beforeEach(function() { | ||
redraw = apiPubSub() | ||
mount = apiMounter(coreRenderer($window), redraw) | ||
redrawService = apiRedraw($window) | ||
mount = apiMounter(redrawService) | ||
render = coreRenderer($window).render | ||
@@ -48,3 +48,3 @@ }) | ||
o("mounting null deletes `redraw` from `root`", function() { | ||
o("mounting null unmounts", function() { | ||
mount(root, { | ||
@@ -56,7 +56,5 @@ view : function() { | ||
o(typeof root.redraw).equals('function') | ||
mount(root, null) | ||
o(typeof root.redraw).equals('undefined') | ||
o(root.childNodes.length).equals(0) | ||
}) | ||
@@ -169,3 +167,3 @@ | ||
var onupdate = o.spy() | ||
var oninit = o.spy() | ||
var oninit = o.spy() | ||
var e = $window.document.createEvent("MouseEvents") | ||
@@ -206,4 +204,4 @@ | ||
return m("div", { | ||
oninit : oninit, | ||
onupdate : onupdate | ||
oninit: oninit, | ||
onupdate: onupdate | ||
}) | ||
@@ -216,3 +214,3 @@ } | ||
redraw.publish() | ||
redrawService.redraw() | ||
@@ -226,2 +224,24 @@ // Wrapped to give time for the rate-limited redraw to fire | ||
}) | ||
o("throttles", function(done, timeout) { | ||
timeout(200) | ||
var i = 0 | ||
mount(root, {view: function() {i++}}) | ||
var before = i | ||
redrawService.redraw() | ||
redrawService.redraw() | ||
redrawService.redraw() | ||
redrawService.redraw() | ||
var after = i | ||
setTimeout(function(){ | ||
o(before).equals(1) // mounts synchronously | ||
o(after).equals(1) // throttles rest | ||
o(i).equals(2) | ||
done() | ||
},40) | ||
}) | ||
}) |
@@ -8,6 +8,7 @@ "use strict" | ||
var m = require("../../render/hyperscript") | ||
var callAsync = require("../../test-utils/callAsync") | ||
var coreRenderer = require("../../render/render") | ||
var apiPubSub = require("../../api/pubsub") | ||
var apiRedraw = require("../../api/redraw") | ||
var apiRouter = require("../../api/router") | ||
var apiMounter = require("../../api/mount") | ||
var Promise = require("../../promise/promise") | ||
@@ -19,3 +20,3 @@ o.spec("route", function() { | ||
var FRAME_BUDGET = Math.floor(1000 / 60) | ||
var $window, root, redraw, mount, route | ||
var $window, root, redrawService, route | ||
@@ -27,5 +28,4 @@ o.beforeEach(function() { | ||
redraw = apiPubSub() | ||
mount = apiMounter(coreRenderer($window), redraw) | ||
route = apiRouter($window, mount) | ||
redrawService = apiRedraw($window) | ||
route = apiRouter($window, redrawService) | ||
route.prefix(prefix) | ||
@@ -65,3 +65,3 @@ }) | ||
redraw.publish(true) | ||
redrawService.redraw() | ||
@@ -82,3 +82,3 @@ o(view.callCount).equals(2) | ||
setTimeout(function() { | ||
callAsync(function() { | ||
o(root.firstChild.nodeName).equals("DIV") | ||
@@ -91,3 +91,3 @@ | ||
done() | ||
}, FRAME_BUDGET) | ||
}) | ||
}) | ||
@@ -131,3 +131,3 @@ | ||
redraw.publish(true) | ||
redrawService.redraw() | ||
@@ -139,4 +139,4 @@ o(onupdate.callCount).equals(1) | ||
var onupdate = o.spy() | ||
var oninit = o.spy() | ||
var onclick = o.spy() | ||
var oninit = o.spy() | ||
var onclick = o.spy() | ||
var e = $window.document.createEvent("MouseEvents") | ||
@@ -169,7 +169,7 @@ | ||
// Wrapped to give time for the rate-limited redraw to fire | ||
setTimeout(function() { | ||
callAsync(function() { | ||
o(onupdate.callCount).equals(1) | ||
done() | ||
}, FRAME_BUDGET * 2) | ||
}) | ||
}) | ||
@@ -179,4 +179,4 @@ | ||
var onupdate = o.spy() | ||
var oninit = o.spy() | ||
var onclick = o.spy() | ||
var oninit = o.spy() | ||
var onclick = o.spy() | ||
var e = $window.document.createEvent("MouseEvents") | ||
@@ -206,7 +206,7 @@ | ||
// Wrapped to ensure no redraw fired | ||
setTimeout(function() { | ||
callAsync(function() { | ||
o(onupdate.callCount).equals(0) | ||
done() | ||
}, FRAME_BUDGET) | ||
}) | ||
}) | ||
@@ -245,3 +245,3 @@ | ||
o("accepts RouteResolver", function() { | ||
o("accepts RouteResolver with onmatch that returns Component", function(done) { | ||
var matchCount = 0 | ||
@@ -251,36 +251,202 @@ var renderCount = 0 | ||
view: function() { | ||
return m("div") | ||
return m("span") | ||
} | ||
} | ||
var resolver = { | ||
onmatch: function(args, requestedPath) { | ||
matchCount++ | ||
o(args.id).equals("abc") | ||
o(requestedPath).equals("/abc") | ||
o(this).equals(resolver) | ||
return Component | ||
}, | ||
render: function(vnode) { | ||
renderCount++ | ||
o(vnode.attrs.id).equals("abc") | ||
o(this).equals(resolver) | ||
return vnode | ||
}, | ||
} | ||
$window.location.href = prefix + "/abc" | ||
route(root, "/abc", { | ||
"/:id" : { | ||
onmatch: function(resolve, args, requestedPath) { | ||
matchCount++ | ||
"/:id" : resolver | ||
}) | ||
o(args.id).equals("abc") | ||
o(requestedPath).equals("/abc") | ||
callAsync(function() { | ||
o(matchCount).equals(1) | ||
o(renderCount).equals(1) | ||
o(root.firstChild.nodeName).equals("SPAN") | ||
done() | ||
}) | ||
}) | ||
resolve(Component) | ||
}, | ||
render: function(vnode) { | ||
renderCount++ | ||
o("accepts RouteResolver with onmatch that returns Promise<Component>", function(done) { | ||
var matchCount = 0 | ||
var renderCount = 0 | ||
var Component = { | ||
view: function() { | ||
return m("span") | ||
} | ||
} | ||
o(vnode.attrs.id).equals("abc") | ||
var resolver = { | ||
onmatch: function(args, requestedPath) { | ||
matchCount++ | ||
return vnode | ||
}, | ||
o(args.id).equals("abc") | ||
o(requestedPath).equals("/abc") | ||
o(this).equals(resolver) | ||
return Promise.resolve(Component) | ||
}, | ||
render: function(vnode) { | ||
renderCount++ | ||
o(vnode.attrs.id).equals("abc") | ||
o(this).equals(resolver) | ||
return vnode | ||
}, | ||
} | ||
$window.location.href = prefix + "/abc" | ||
route(root, "/abc", { | ||
"/:id" : resolver | ||
}) | ||
o(matchCount).equals(1) | ||
o(renderCount).equals(1) | ||
o(root.firstChild.nodeName).equals("DIV") | ||
callAsync(function() { | ||
o(matchCount).equals(1) | ||
o(renderCount).equals(1) | ||
o(root.firstChild.nodeName).equals("SPAN") | ||
done() | ||
}) | ||
}) | ||
o("accepts RouteResolver without `render` method as payload", function() { | ||
o("accepts RouteResolver with onmatch that returns Promise<undefined>", function(done) { | ||
var matchCount = 0 | ||
var renderCount = 0 | ||
var Component = { | ||
view: function() { | ||
return m("span") | ||
} | ||
} | ||
var resolver = { | ||
onmatch: function(args, requestedPath) { | ||
matchCount++ | ||
o(args.id).equals("abc") | ||
o(requestedPath).equals("/abc") | ||
o(this).equals(resolver) | ||
return Promise.resolve() | ||
}, | ||
render: function(vnode) { | ||
renderCount++ | ||
o(vnode.attrs.id).equals("abc") | ||
o(this).equals(resolver) | ||
return vnode | ||
}, | ||
} | ||
$window.location.href = prefix + "/abc" | ||
route(root, "/abc", { | ||
"/:id" : resolver | ||
}) | ||
callAsync(function() { | ||
o(matchCount).equals(1) | ||
o(renderCount).equals(1) | ||
o(root.firstChild.nodeName).equals("DIV") | ||
done() | ||
}) | ||
}) | ||
o("accepts RouteResolver with onmatch that returns Promise<any>", function(done) { | ||
var matchCount = 0 | ||
var renderCount = 0 | ||
var Component = { | ||
view: function() { | ||
return m("span") | ||
} | ||
} | ||
var resolver = { | ||
onmatch: function(args, requestedPath) { | ||
matchCount++ | ||
o(args.id).equals("abc") | ||
o(requestedPath).equals("/abc") | ||
o(this).equals(resolver) | ||
return Promise.resolve([]) | ||
}, | ||
render: function(vnode) { | ||
renderCount++ | ||
o(vnode.attrs.id).equals("abc") | ||
o(this).equals(resolver) | ||
return vnode | ||
}, | ||
} | ||
$window.location.href = prefix + "/abc" | ||
route(root, "/abc", { | ||
"/:id" : resolver | ||
}) | ||
callAsync(function() { | ||
o(matchCount).equals(1) | ||
o(renderCount).equals(1) | ||
o(root.firstChild.nodeName).equals("DIV") | ||
done() | ||
}) | ||
}) | ||
o("accepts RouteResolver with onmatch that returns rejected Promise", function(done) { | ||
var matchCount = 0 | ||
var renderCount = 0 | ||
var spy = o.spy() | ||
var Component = { | ||
view: function() { | ||
return m("span") | ||
} | ||
} | ||
var resolver = { | ||
onmatch: function(args, requestedPath) { | ||
matchCount++ | ||
return Promise.reject(new Error("error")) | ||
}, | ||
render: function(vnode) { | ||
renderCount++ | ||
return vnode | ||
}, | ||
} | ||
$window.location.href = prefix + "/test/1" | ||
route(root, "/default", { | ||
"/default" : {view: spy}, | ||
"/test/:id" : resolver | ||
}) | ||
callAsync(function() { | ||
callAsync(function() { | ||
o(matchCount).equals(1) | ||
o(renderCount).equals(0) | ||
o(spy.callCount).equals(1) | ||
done() | ||
}) | ||
}) | ||
}) | ||
o("accepts RouteResolver without `render` method as payload", function(done) { | ||
var matchCount = 0 | ||
var Component = { | ||
view: function() { | ||
return m("div") | ||
@@ -293,3 +459,3 @@ } | ||
"/:id" : { | ||
onmatch: function(resolve, args, requestedPath) { | ||
onmatch: function(args, requestedPath) { | ||
matchCount++ | ||
@@ -300,3 +466,3 @@ | ||
resolve(Component) | ||
return Component | ||
}, | ||
@@ -306,14 +472,14 @@ }, | ||
o(matchCount).equals(1) | ||
o(root.firstChild.nodeName).equals("DIV") | ||
callAsync(function() { | ||
o(matchCount).equals(1) | ||
o(root.firstChild.nodeName).equals("DIV") | ||
done() | ||
}) | ||
}) | ||
o("changing `vnode.key` in `render` resets the component", function(done, timeout){ | ||
timeout(FRAME_BUDGET * 6) | ||
var oninit = o.spy() | ||
var Component = { | ||
oninit: oninit, | ||
view: function(){ | ||
view: function() { | ||
return m("div") | ||
@@ -328,10 +494,10 @@ } | ||
}) | ||
setTimeout(function(){ | ||
callAsync(function() { | ||
o(oninit.callCount).equals(1) | ||
route.set('/def') | ||
setTimeout(function(){ | ||
route.set("/def") | ||
callAsync(function() { | ||
o(oninit.callCount).equals(2) | ||
done() | ||
}, FRAME_BUDGET) | ||
}, FRAME_BUDGET) | ||
}) | ||
}) | ||
}) | ||
@@ -390,10 +556,10 @@ | ||
setTimeout(function() { | ||
callAsync(function() { | ||
o(root.firstChild).equals(dom) | ||
done() | ||
}, FRAME_BUDGET) | ||
}) | ||
}) | ||
o("calls onmatch and view correct number of times", function() { | ||
o("calls onmatch and view correct number of times", function(done) { | ||
var matchCount = 0 | ||
@@ -410,5 +576,5 @@ var renderCount = 0 | ||
"/" : { | ||
onmatch: function(resolve) { | ||
onmatch: function() { | ||
matchCount++ | ||
resolve(Component) | ||
return Component | ||
}, | ||
@@ -422,14 +588,54 @@ render: function(vnode) { | ||
o(matchCount).equals(1) | ||
o(renderCount).equals(1) | ||
callAsync(function() { | ||
o(matchCount).equals(1) | ||
o(renderCount).equals(1) | ||
redraw.publish(true) | ||
redrawService.redraw() | ||
o(matchCount).equals(1) | ||
o(renderCount).equals(2) | ||
o(matchCount).equals(1) | ||
o(renderCount).equals(2) | ||
done() | ||
}) | ||
}) | ||
o("calls onmatch and view correct number of times when not onmatch returns undefined", function(done) { | ||
var matchCount = 0 | ||
var renderCount = 0 | ||
var Component = { | ||
view: function() { | ||
return m("div") | ||
} | ||
} | ||
$window.location.href = prefix + "/" | ||
route(root, "/", { | ||
"/" : { | ||
onmatch: function() { | ||
matchCount++ | ||
}, | ||
render: function(vnode) { | ||
renderCount++ | ||
return {tag: Component} | ||
}, | ||
}, | ||
}) | ||
callAsync(function() { | ||
o(matchCount).equals(1) | ||
o(renderCount).equals(1) | ||
redrawService.redraw() | ||
o(matchCount).equals(1) | ||
o(renderCount).equals(2) | ||
done() | ||
}) | ||
}) | ||
o("onmatch can redirect to another route", function(done) { | ||
var redirected = false | ||
var render = o.spy() | ||
$window.location.href = prefix + "/a" | ||
@@ -440,6 +646,7 @@ route(root, "/a", { | ||
route.set("/b") | ||
} | ||
}, | ||
render: render | ||
}, | ||
"/b" : { | ||
view: function(vnode){ | ||
view: function() { | ||
redirected = true | ||
@@ -450,11 +657,14 @@ } | ||
setTimeout(function() { | ||
callAsync(function() { | ||
o(render.callCount).equals(0) | ||
o(redirected).equals(true) | ||
done() | ||
}, FRAME_BUDGET) | ||
}) | ||
}) | ||
o("onmatch can redirect to another route that has RouteResolver", function(done) { | ||
o("onmatch can redirect to another route that has RouteResolver w/ only onmatch", function(done) { | ||
var redirected = false | ||
var render = o.spy() | ||
var view = o.spy(function() {return m("div")}) | ||
@@ -466,3 +676,37 @@ $window.location.href = prefix + "/a" | ||
route.set("/b") | ||
}, | ||
render: render | ||
}, | ||
"/b" : { | ||
onmatch: function() { | ||
redirected = true | ||
return {view: view} | ||
} | ||
} | ||
}) | ||
callAsync(function() { | ||
callAsync(function() { | ||
o(render.callCount).equals(0) | ||
o(redirected).equals(true) | ||
o(view.callCount).equals(1) | ||
o(root.childNodes.length).equals(1) | ||
o(root.firstChild.nodeName).equals("DIV") | ||
done() | ||
}) | ||
}) | ||
}) | ||
o("onmatch can redirect to another route that has RouteResolver w/ only render", function(done) { | ||
var redirected = false | ||
var render = o.spy() | ||
$window.location.href = prefix + "/a" | ||
route(root, "/a", { | ||
"/a" : { | ||
onmatch: function() { | ||
route.set("/b") | ||
}, | ||
render: render | ||
}, | ||
@@ -476,41 +720,215 @@ "/b" : { | ||
setTimeout(function() { | ||
callAsync(function() { | ||
o(render.callCount).equals(0) | ||
o(redirected).equals(true) | ||
done() | ||
}, FRAME_BUDGET) | ||
}) | ||
}) | ||
o("onmatch resolution callback resolves at most once", function(done) { | ||
var resolveCount = 0 | ||
var resolvedComponent | ||
var A = {view: function() {}} | ||
var B = {view: function() {}} | ||
var C = {view: function() {}} | ||
o("onmatch can redirect to another route that has RouteResolver whose onmatch resolves asynchronously", function(done) { | ||
var redirected = false | ||
var render = o.spy() | ||
var view = o.spy() | ||
$window.location.href = prefix + "/" | ||
route(root, "/", { | ||
"/": { | ||
onmatch: function(resolve) { | ||
resolve(A) | ||
resolve(B) | ||
callAsync(function() {resolve(C)}) | ||
$window.location.href = prefix + "/a" | ||
route(root, "/a", { | ||
"/a" : { | ||
onmatch: function() { | ||
route.set("/b") | ||
}, | ||
render: render | ||
}, | ||
"/b" : { | ||
onmatch: function() { | ||
redirected = true | ||
return new Promise(function(fulfill){ | ||
callAsync(function(){ | ||
fulfill({view: view}) | ||
}) | ||
}) | ||
} | ||
} | ||
}) | ||
callAsync(function() { | ||
callAsync(function() { | ||
callAsync(function() { | ||
o(render.callCount).equals(0) | ||
o(redirected).equals(true) | ||
o(view.callCount).equals(1) | ||
done() | ||
}) | ||
}) | ||
}) | ||
}) | ||
o("onmatch can redirect to another route asynchronously", function(done) { | ||
var redirected = false | ||
var render = o.spy() | ||
var view = o.spy() | ||
$window.location.href = prefix + "/a" | ||
route(root, "/a", { | ||
"/a" : { | ||
onmatch: function() { | ||
callAsync(function() {route.set("/b")}) | ||
return new Promise(function() {}) | ||
}, | ||
render: render | ||
}, | ||
"/b" : { | ||
onmatch: function() { | ||
redirected = true | ||
return {view: view} | ||
} | ||
} | ||
}) | ||
callAsync(function() { | ||
callAsync(function() { | ||
callAsync(function() { | ||
o(render.callCount).equals(0) | ||
o(redirected).equals(true) | ||
o(view.callCount).equals(1) | ||
done() | ||
}) | ||
}) | ||
}) | ||
}) | ||
o("onmatch can redirect w/ window.history.back()", function(done) { | ||
var render = o.spy() | ||
var component = {view: o.spy()} | ||
$window.location.href = prefix + "/a" | ||
route(root, "/a", { | ||
"/a" : { | ||
onmatch: function() { | ||
return component | ||
}, | ||
render: function(vnode) { | ||
resolveCount++ | ||
resolvedComponent = vnode.tag | ||
return vnode | ||
} | ||
}, | ||
"/b" : { | ||
onmatch: function() { | ||
$window.history.back() | ||
return new Promise(function() {}) | ||
}, | ||
render: render | ||
} | ||
}) | ||
setTimeout(function() { | ||
o(resolveCount).equals(1) | ||
o(resolvedComponent).equals(A) | ||
done() | ||
}, FRAME_BUDGET) | ||
callAsync(function() { | ||
route.set('/b') | ||
callAsync(function() { | ||
callAsync(function() { | ||
callAsync(function() { | ||
o(render.callCount).equals(0) | ||
o(component.view.callCount).equals(2) | ||
done() | ||
}) | ||
}) | ||
}) | ||
}) | ||
}) | ||
o("onmatch can redirect to a non-existent route that defaults to a RouteResolver w/ onmatch", function(done) { | ||
var redirected = false | ||
var render = o.spy() | ||
$window.location.href = prefix + "/a" | ||
route(root, "/b", { | ||
"/a" : { | ||
onmatch: function() { | ||
route.set("/c") | ||
}, | ||
render: render | ||
}, | ||
"/b" : { | ||
onmatch: function(vnode){ | ||
redirected = true | ||
return {view: function() {}} | ||
} | ||
} | ||
}) | ||
callAsync(function() { | ||
callAsync(function() { | ||
o(render.callCount).equals(0) | ||
o(redirected).equals(true) | ||
done() | ||
}) | ||
}) | ||
}) | ||
o("onmatch can redirect to a non-existent route that defaults to a RouteResolver w/ render", function(done) { | ||
var redirected = false | ||
var render = o.spy() | ||
$window.location.href = prefix + "/a" | ||
route(root, "/b", { | ||
"/a" : { | ||
onmatch: function() { | ||
route.set("/c") | ||
}, | ||
render: render | ||
}, | ||
"/b" : { | ||
render: function(vnode){ | ||
redirected = true | ||
} | ||
} | ||
}) | ||
callAsync(function() { | ||
callAsync(function() { | ||
o(render.callCount).equals(0) | ||
o(redirected).equals(true) | ||
done() | ||
}) | ||
}) | ||
}) | ||
o("onmatch can redirect to a non-existent route that defaults to a component", function(done) { | ||
var redirected = false | ||
var render = o.spy() | ||
$window.location.href = prefix + "/a" | ||
route(root, "/b", { | ||
"/a" : { | ||
onmatch: function() { | ||
route.set("/c") | ||
}, | ||
render: render | ||
}, | ||
"/b" : { | ||
view: function(vnode){ | ||
redirected = true | ||
} | ||
} | ||
}) | ||
callAsync(function() { | ||
callAsync(function() { | ||
o(render.callCount).equals(0) | ||
o(redirected).equals(true) | ||
done() | ||
}) | ||
}) | ||
}) | ||
o("the previous view redraws while onmatch resolution is pending (#1268)", function(done) { | ||
var view = o.spy() | ||
var onmatch = o.spy() | ||
var onmatch = o.spy(function() { | ||
return new Promise(function() {}) | ||
}) | ||
@@ -528,7 +946,7 @@ $window.location.href = prefix + "/a" | ||
setTimeout(function(){ | ||
callAsync(function() { | ||
o(view.callCount).equals(1) | ||
o(onmatch.callCount).equals(1) | ||
redraw.publish(true) | ||
redrawService.redraw() | ||
@@ -539,25 +957,32 @@ o(view.callCount).equals(2) | ||
done() | ||
}, FRAME_BUDGET) | ||
}) | ||
}) | ||
o("m.route.set(m.route.get()) re-runs the resolution logic (#1180)", function(done){ | ||
var onmatch = o.spy(function(resolve){resolve()}) | ||
var onmatch = o.spy() | ||
var render = o.spy(function() {return m("div")}) | ||
$window.location.href = prefix + "/" | ||
route(root, '/', { | ||
"/":{ | ||
"/": { | ||
onmatch: onmatch, | ||
render: function(){return m("div")} | ||
render: render | ||
} | ||
}) | ||
o(onmatch.callCount).equals(1) | ||
callAsync(function() { | ||
o(onmatch.callCount).equals(1) | ||
o(render.callCount).equals(1) | ||
route.set(route.get()) | ||
route.set(route.get()) | ||
setTimeout(function() { | ||
o(onmatch.callCount).equals(2) | ||
callAsync(function() { | ||
callAsync(function() { | ||
o(onmatch.callCount).equals(2) | ||
o(render.callCount).equals(2) | ||
done() | ||
}, FRAME_BUDGET) | ||
done() | ||
}) | ||
}) | ||
}) | ||
}) | ||
@@ -569,4 +994,8 @@ | ||
route(root, "/", { | ||
"/": {view: function(){}}, | ||
"/2": {onmatch: function(){}} | ||
"/": {view: function() {}}, | ||
"/2": { | ||
onmatch: function() { | ||
return new Promise(function() {}) | ||
} | ||
} | ||
}) | ||
@@ -579,11 +1008,9 @@ | ||
setTimeout(function(){ | ||
callAsync(function() { | ||
o(route.get()).equals("/") | ||
done() | ||
}, FRAME_BUDGET) | ||
}) | ||
}) | ||
o("routing with RouteResolver works more than once", function(done, timeout) { | ||
timeout(200) | ||
o("routing with RouteResolver works more than once", function(done) { | ||
$window.location.href = prefix + "/a" | ||
@@ -605,16 +1032,52 @@ route(root, '/a', { | ||
setTimeout(function(){ | ||
callAsync(function() { | ||
route.set('/a') | ||
setTimeout(function(){ | ||
callAsync(function() { | ||
o(root.firstChild.nodeName).equals("A") | ||
done() | ||
}, FRAME_BUDGET) | ||
}, FRAME_BUDGET) | ||
}) | ||
}) | ||
}) | ||
o("calling route.set invalidates pending onmatch resolution", function(done, timeout) { | ||
timeout(200) | ||
o("calling route.set invalidates pending onmatch resolution", function(done) { | ||
var rendered = false | ||
var resolved | ||
$window.location.href = prefix + "/a" | ||
route(root, "/a", { | ||
"/a": { | ||
onmatch: function() { | ||
return new Promise(function(resolve) { | ||
callAsync(function() { | ||
callAsync(function() { | ||
resolve({view: function() {}}) | ||
}) | ||
}) | ||
}) | ||
}, | ||
render: function(vnode) { | ||
rendered = true | ||
resolved = "a" | ||
} | ||
}, | ||
"/b": { | ||
view: function() { | ||
resolved = "b" | ||
} | ||
} | ||
}) | ||
route.set("/b") | ||
callAsync(function() { | ||
o(rendered).equals(false) | ||
o(resolved).equals("b") | ||
done() | ||
}) | ||
}) | ||
o("calling route.set invalidates pending onmatch resolution", function(done) { | ||
var rendered = false | ||
var resolved | ||
@@ -624,9 +1087,20 @@ $window.location.href = prefix + "/a" | ||
"/a": { | ||
onmatch: function(resolve) { | ||
setTimeout(resolve, 20) | ||
onmatch: function() { | ||
return new Promise(function(resolve) { | ||
callAsync(function() { | ||
callAsync(function() { | ||
resolve({view: function() {rendered = true}}) | ||
}) | ||
}) | ||
}) | ||
}, | ||
render: function(vnode) {resolved = "a"} | ||
render: function(vnode) { | ||
rendered = true | ||
resolved = "a" | ||
} | ||
}, | ||
"/b": { | ||
view: function() {resolved = "b"} | ||
view: function() { | ||
resolved = "b" | ||
} | ||
} | ||
@@ -637,8 +1111,93 @@ }) | ||
setTimeout(function() { | ||
callAsync(function() { | ||
o(rendered).equals(false) | ||
o(resolved).equals("b") | ||
callAsync(function() { | ||
o(rendered).equals(false) | ||
o(resolved).equals("b") | ||
done() | ||
}) | ||
}) | ||
}) | ||
o("route changes activate onbeforeremove", function(done) { | ||
var spy = o.spy() | ||
$window.location.href = prefix + "/a" | ||
route(root, "/a", { | ||
"/a": { | ||
onbeforeremove: spy, | ||
view: function() {} | ||
}, | ||
"/b": { | ||
view: function() {} | ||
} | ||
}) | ||
route.set("/b") | ||
callAsync(function() { | ||
o(spy.callCount).equals(1) | ||
done() | ||
}, 30) | ||
}) | ||
}) | ||
o("asynchronous route.set in onmatch works", function(done) { | ||
var rendered = false, resolved | ||
route(root, "/a", { | ||
"/a": { | ||
onmatch: function() { | ||
return Promise.resolve().then(function() { | ||
route.set("/b") | ||
}) | ||
}, | ||
render: function(vnode) { | ||
rendered = true | ||
resolved = "a" | ||
} | ||
}, | ||
"/b": { | ||
view: function() { | ||
resolved = "b" | ||
} | ||
}, | ||
}) | ||
callAsync(function() { // tick for popstate for /a | ||
callAsync(function() { // tick for promise in onmatch | ||
callAsync(function() { // tick for onpopstate for /b | ||
o(rendered).equals(false) | ||
o(resolved).equals("b") | ||
done() | ||
}) | ||
}) | ||
}) | ||
}) | ||
o("throttles", function(done, timeout) { | ||
timeout(200) | ||
var i = 0 | ||
$window.location.href = prefix + "/" | ||
route(root, "/", { | ||
"/": {view: function(v) {i++}} | ||
}) | ||
var before = i | ||
redrawService.redraw() | ||
redrawService.redraw() | ||
redrawService.redraw() | ||
redrawService.redraw() | ||
var after = i | ||
setTimeout(function() { | ||
o(before).equals(1) // routes synchronously | ||
o(after).equals(2) // redraws synchronously | ||
o(i).equals(3) // throttles rest | ||
done() | ||
}, FRAME_BUDGET * 2) | ||
}) | ||
}) | ||
@@ -645,0 +1204,0 @@ }) |
@@ -18,2 +18,3 @@ "use strict" | ||
var error | ||
function run(input, output) { | ||
@@ -35,4 +36,5 @@ try { | ||
var dependency = resolve(filepath, filename) | ||
var code = process(dependency, pre + (modules[dependency] == null ? exportCode(filename, dependency, def, variable, eq, rest, uuid) : def + variable + eq + modules[dependency])) | ||
modules[dependency] = rest ? "_" + uuid : variable | ||
var localUUID = uuid // global uuid can update from nested `process` call, ensure same id is used on declaration and consumption | ||
var code = process(dependency, pre + (modules[dependency] == null ? exportCode(filename, dependency, def, variable, eq, rest, localUUID) : def + variable + eq + modules[dependency])) | ||
modules[dependency] = rest ? "_" + localUUID : variable | ||
uuid++ | ||
@@ -61,4 +63,7 @@ return code + rest | ||
try {new Function(code)} catch (e) { | ||
proc.exec("node " + filename, function(error) { | ||
if (error !== null) console.log("\x1b[31m" + error.message) | ||
proc.exec("node " + filepath, function(e) { | ||
if (e !== null && e.message !== error) { | ||
error = e.message | ||
console.log("\x1b[31m" + e.message + "\x1b[0m") | ||
} | ||
}) | ||
@@ -117,3 +122,7 @@ } | ||
if (!isFile(output) || code !== read(output)) fs.writeFileSync(output, code, "utf8") | ||
if (!isFile(output) || code !== read(output)) { | ||
//try {new Function(code); console.log("build completed at " + new Date())} catch (e) {} | ||
error = null | ||
fs.writeFileSync(output, code, "utf8") | ||
} | ||
} | ||
@@ -120,0 +129,0 @@ catch (e) { |
@@ -276,2 +276,26 @@ var o = require("../../ospec/ospec") | ||
}) | ||
o("works if included multiple times", function() { | ||
write("a.js", `module.exports = 123`) | ||
write("b.js", `var a = require("./a").toString()\nmodule.exports = a`) | ||
write("c.js", `var a = require("./a").toString()\nvar b = require("./b")`) | ||
bundle(ns + "c.js", ns + "out.js") | ||
o(read("out.js")).equals(`new function() {\nvar _0 = 123\nvar a = _0.toString()\nvar a0 = _0.toString()\nvar b = a0\n}`) | ||
remove("a.js") | ||
remove("b.js") | ||
remove("c.js") | ||
}) | ||
o("works if included multiple times reverse", function() { | ||
write("a.js", `module.exports = 123`) | ||
write("b.js", `var a = require("./a").toString()\nmodule.exports = a`) | ||
write("c.js", `var b = require("./b")\nvar a = require("./a").toString()`) | ||
bundle(ns + "c.js", ns + "out.js") | ||
o(read("out.js")).equals(`new function() {\nvar _0 = 123\nvar a0 = _0.toString()\nvar b = a0\nvar a = _0.toString()\n}`) | ||
remove("a.js") | ||
remove("b.js") | ||
remove("c.js") | ||
}) | ||
o("reuses binding if possible", function() { | ||
@@ -278,0 +302,0 @@ write("a.js", `var b = require("./b")\nvar c = require("./c")`) |
@@ -7,3 +7,3 @@ "use strict" | ||
requestService.setCompletionCallback(redrawService.publish) | ||
requestService.setCompletionCallback(redrawService.redraw) | ||
@@ -14,3 +14,3 @@ m.mount = require("./mount") | ||
m.render = require("./render").render | ||
m.redraw = redrawService.publish | ||
m.redraw = redrawService.redraw | ||
m.request = requestService.request | ||
@@ -17,0 +17,0 @@ m.jsonp = requestService.jsonp |
422
mithril.js
@@ -33,3 +33,4 @@ new function() { | ||
if (attrValue) attrValue = attrValue.replace(/\\(["'])/g, "$1").replace(/\\\\/g, "\\") | ||
attributes[match[4]] = attrValue || true | ||
if (match[4] === "class") classes.push(attrValue) | ||
else attributes[match[4]] = attrValue || true | ||
} | ||
@@ -205,27 +206,34 @@ } | ||
var callbackCount = 0 | ||
var count = 0 | ||
var oncompletion | ||
function setCompletionCallback(callback) {oncompletion = callback} | ||
function complete() {if (--count === 0 && typeof oncompletion === "function") oncompletion()} | ||
function finalize(promise0) { | ||
var then0 = promise0.then | ||
promise0.then = function() { | ||
count++ | ||
var next = then0.apply(promise0, arguments) | ||
next.then(complete, function(e) { | ||
complete() | ||
throw e | ||
}) | ||
return finalize(next) | ||
function finalizer() { | ||
var count = 0 | ||
function complete() {if (--count === 0 && typeof oncompletion === "function") oncompletion()} | ||
return function finalize(promise0) { | ||
var then0 = promise0.then | ||
promise0.then = function() { | ||
count++ | ||
var next = then0.apply(promise0, arguments) | ||
next.then(complete, function(e) { | ||
complete() | ||
if (count === 0) throw e | ||
}) | ||
return finalize(next) | ||
} | ||
return promise0 | ||
} | ||
return promise0 | ||
} | ||
function normalize(args, extra) { | ||
if (typeof args === "string") { | ||
var url = args | ||
args = extra || {} | ||
if (args.url == null) args.url = url | ||
} | ||
return args | ||
} | ||
function request(args, extra) { | ||
return finalize(new Promise(function(resolve, reject) { | ||
if (typeof args === "string") { | ||
var url = args | ||
args = extra || {} | ||
if (args.url == null) args.url = url | ||
} | ||
var finalize = finalizer() | ||
args = normalize(args, extra) | ||
var promise0 = new Promise(function(resolve, reject) { | ||
if (args.method == null) args.method = "GET" | ||
@@ -248,2 +256,3 @@ args.method = args.method.toUpperCase() | ||
} | ||
if (args.withCredentials) xhr.withCredentials = args.withCredentials | ||
if (typeof args.config === "function") xhr = args.config(xhr, args) || xhr | ||
@@ -270,6 +279,10 @@ xhr.onreadystatechange = function() { | ||
else xhr.send() | ||
})) | ||
}) | ||
return args.background === true ? promise0 : finalize(promise0) | ||
} | ||
function jsonp(args) { | ||
return finalize(new Promise(function(resolve, reject) { | ||
function jsonp(args, extra) { | ||
var finalize = finalizer() | ||
args = normalize(args, extra) | ||
var promise0 = new Promise(function(resolve, reject) { | ||
var callbackName = args.callbackName || "_mithril_" + Math.round(Math.random() * 1e16) + "_" + callbackCount++ | ||
@@ -292,3 +305,4 @@ var script = $window.document.createElement("script") | ||
$window.document.documentElement.appendChild(script) | ||
})) | ||
}) | ||
return args.background === true? promise0 : finalize(promise0) | ||
} | ||
@@ -334,18 +348,3 @@ function interpolate(url, data) { | ||
var requestService = _8(window, PromisePolyfill) | ||
var _11 = function() { | ||
var callbacks = [] | ||
function unsubscribe(callback) { | ||
var index = callbacks.indexOf(callback) | ||
if (index > -1) callbacks.splice(index, 1) | ||
} | ||
function publish() { | ||
for (var i = 0; i < callbacks.length; i++) { | ||
callbacks[i].apply(this, arguments) | ||
} | ||
} | ||
return {subscribe: callbacks.push.bind(callbacks), unsubscribe: unsubscribe, publish: publish} | ||
} | ||
var redrawService = _11() | ||
requestService.setCompletionCallback(redrawService.publish) | ||
var _13 = function($window) { | ||
var coreRenderer = function($window) { | ||
var $doc = $window.document | ||
@@ -463,14 +462,20 @@ var $emptyFragment = $doc.createDocumentFragment() | ||
else { | ||
var recycling = isRecyclable(old, vnodes) | ||
if (recycling) old = old.concat(old.pool) | ||
if (old.length === vnodes.length && vnodes[0] != null && vnodes[0].key == null) { | ||
var isUnkeyed = false | ||
for (var i = 0; i < vnodes.length; i++) { | ||
if (vnodes[i] != null) { | ||
isUnkeyed = vnodes[i].key == null | ||
break | ||
} | ||
} | ||
if (old.length === vnodes.length && isUnkeyed) { | ||
for (var i = 0; i < old.length; i++) { | ||
if (old[i] === vnodes[i] || old[i] == null && vnodes[i] == null) continue | ||
if (old[i] === vnodes[i]) continue | ||
else if (old[i] == null) insertNode(parent, createNode(vnodes[i], hooks, ns), getNextSibling(old, i + 1, nextSibling)) | ||
else if (vnodes[i] == null) removeNodes(old, i, i + 1, vnodes) | ||
else updateNode(parent, old[i], vnodes[i], hooks, getNextSibling(old, i + 1, nextSibling), recycling, ns) | ||
if (recycling && old[i].tag === vnodes[i].tag) insertNode(parent, toFragment(old[i]), getNextSibling(old, i + 1, nextSibling)) | ||
else updateNode(parent, old[i], vnodes[i], hooks, getNextSibling(old, i + 1, nextSibling), false, ns) | ||
} | ||
} | ||
else { | ||
var recycling = isRecyclable(old, vnodes) | ||
if (recycling) old = old.concat(old.pool) | ||
var oldStart = 0, start = 0, oldEnd = old.length - 1, end = vnodes.length - 1, map | ||
@@ -480,3 +485,5 @@ while (oldEnd >= oldStart && end >= start) { | ||
if (o === v && !recycling) oldStart++, start++ | ||
else if (o != null && v != null && o.key === v.key) { | ||
else if (o == null) oldStart++ | ||
else if (v == null) start++ | ||
else if (o.key === v.key) { | ||
oldStart++, start++ | ||
@@ -489,3 +496,5 @@ updateNode(parent, o, v, hooks, getNextSibling(old, oldStart, nextSibling), recycling, ns) | ||
if (o === v && !recycling) oldEnd--, start++ | ||
else if (o != null && v != null && o.key === v.key) { | ||
else if (o == null) oldEnd-- | ||
else if (v == null) start++ | ||
else if (o.key === v.key) { | ||
updateNode(parent, o, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), recycling, ns) | ||
@@ -501,3 +510,5 @@ if (recycling || start < end) insertNode(parent, toFragment(o), getNextSibling(old, oldStart, nextSibling)) | ||
if (o === v && !recycling) oldEnd--, end-- | ||
else if (o != null && v != null && o.key === v.key) { | ||
else if (o == null) oldEnd-- | ||
else if (v == null) end-- | ||
else if (o.key === v.key) { | ||
updateNode(parent, o, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), recycling, ns) | ||
@@ -647,4 +658,4 @@ if (recycling && o.tag === v.tag) insertNode(parent, toFragment(o), nextSibling) | ||
if (vnode != null) { | ||
var key1 = vnode.key | ||
if (key1 != null) map[key1] = i | ||
var key2 = vnode.key | ||
if (key2 != null) map[key2] = i | ||
} | ||
@@ -683,3 +694,3 @@ } | ||
} | ||
else if (children != null || vnode.text != null) throw new Error("Child node of a contenteditable must be trusted") | ||
else if (vnode.text != null || children != null && children.length !== 0) throw new Error("Child node of a contenteditable must be trusted") | ||
} | ||
@@ -756,26 +767,30 @@ //remove | ||
function setAttrs(vnode, attrs2, ns) { | ||
for (var key1 in attrs2) { | ||
setAttr(vnode, key1, null, attrs2[key1], ns) | ||
for (var key2 in attrs2) { | ||
setAttr(vnode, key2, null, attrs2[key2], ns) | ||
} | ||
} | ||
function setAttr(vnode, key1, old, value, ns) { | ||
function setAttr(vnode, key2, old, value, ns) { | ||
var element = vnode.dom | ||
if (key1 === "key" || (old === value && !isFormAttribute(vnode, key1)) && typeof value !== "object" || typeof value === "undefined" || isLifecycleMethod(key1)) return | ||
var nsLastIndex = key1.indexOf(":") | ||
if (nsLastIndex > -1 && key1.substr(0, nsLastIndex) === "xlink") { | ||
element.setAttributeNS("http://www.w3.org/1999/xlink", key1.slice(nsLastIndex + 1), value) | ||
if (key2 === "key" || (old === value && !isFormAttribute(vnode, key2)) && typeof value !== "object" || typeof value === "undefined" || isLifecycleMethod(key2)) return | ||
var nsLastIndex = key2.indexOf(":") | ||
if (nsLastIndex > -1 && key2.substr(0, nsLastIndex) === "xlink") { | ||
element.setAttributeNS("http://www.w3.org/1999/xlink", key2.slice(nsLastIndex + 1), value) | ||
} | ||
else if (key1[0] === "o" && key1[1] === "n" && typeof value === "function") updateEvent(vnode, key1, value) | ||
else if (key1 === "style") updateStyle(element, old, value) | ||
else if (key1 in element && !isAttribute(key1) && ns === undefined) { | ||
else if (key2[0] === "o" && key2[1] === "n" && typeof value === "function") updateEvent(vnode, key2, value) | ||
else if (key2 === "style") updateStyle(element, old, value) | ||
else if (key2 in element && !isAttribute(key2) && ns === undefined) { | ||
//setting input[value] to same value by typing on focused element moves cursor to end in Chrome | ||
if (vnode.tag === "input" && key1 === "value" && vnode.dom.value === value && vnode.dom === $doc.activeElement) return | ||
element[key1] = value | ||
if (vnode.tag === "input" && key2 === "value" && vnode.dom.value === value && vnode.dom === $doc.activeElement) return | ||
//setting select[value] to same value while having select open blinks select dropdown in Chrome | ||
if (vnode.tag === "select" && key2 === "value" && vnode.dom.value === value && vnode.dom === $doc.activeElement) return | ||
//setting option[value] to same value while having select open blinks select dropdown in Chrome | ||
if (vnode.tag === "option" && key2 === "value" && vnode.dom.value === value) return | ||
element[key2] = value | ||
} | ||
else { | ||
if (typeof value === "boolean") { | ||
if (value) element.setAttribute(key1, "") | ||
else element.removeAttribute(key1) | ||
if (value) element.setAttribute(key2, "") | ||
else element.removeAttribute(key2) | ||
} | ||
else element.setAttribute(key1 === "className" ? "class" : key1, value) | ||
else element.setAttribute(key2 === "className" ? "class" : key2, value) | ||
} | ||
@@ -792,12 +807,12 @@ } | ||
if (attrs2 != null) { | ||
for (var key1 in attrs2) { | ||
setAttr(vnode, key1, old && old[key1], attrs2[key1], ns) | ||
for (var key2 in attrs2) { | ||
setAttr(vnode, key2, old && old[key2], attrs2[key2], ns) | ||
} | ||
} | ||
if (old != null) { | ||
for (var key1 in old) { | ||
if (attrs2 == null || !(key1 in attrs2)) { | ||
if (key1 === "className") key1 = "class" | ||
if (key1[0] === "o" && key1[1] === "n" && !isLifecycleMethod(key1)) updateEvent(vnode, key1, undefined) | ||
else if (key1 !== "key") vnode.dom.removeAttribute(key1) | ||
for (var key2 in old) { | ||
if (attrs2 == null || !(key2 in attrs2)) { | ||
if (key2 === "className") key2 = "class" | ||
if (key2[0] === "o" && key2[1] === "n" && !isLifecycleMethod(key2)) updateEvent(vnode, key2, undefined) | ||
else if (key2 !== "key") vnode.dom.removeAttribute(key2) | ||
} | ||
@@ -826,8 +841,8 @@ } | ||
if (typeof old === "string") element.style.cssText = "" | ||
for (var key1 in style) { | ||
element.style[key1] = style[key1] | ||
for (var key2 in style) { | ||
element.style[key2] = style[key2] | ||
} | ||
if (old != null && typeof old !== "string") { | ||
for (var key1 in old) { | ||
if (!(key1 in style)) element.style[key1] = "" | ||
for (var key2 in old) { | ||
if (!(key2 in style)) element.style[key2] = "" | ||
} | ||
@@ -838,17 +853,18 @@ } | ||
//event | ||
function updateEvent(vnode, key1, value) { | ||
function updateEvent(vnode, key2, value) { | ||
var element = vnode.dom | ||
var callback = function(e) { | ||
var callback = typeof onevent !== "function" ? value : function(e) { | ||
var result = value.call(element, e) | ||
if (typeof onevent === "function") onevent.call(element, e) | ||
onevent.call(element, e) | ||
return result | ||
} | ||
if (key1 in element) element[key1] = typeof value === "function" ? callback : null | ||
if (key2 in element) element[key2] = typeof value === "function" ? callback : null | ||
else { | ||
var eventName = key1.slice(2) | ||
var eventName = key2.slice(2) | ||
if (vnode.events === undefined) vnode.events = {} | ||
if (vnode.events[key1] != null) element.removeEventListener(eventName, vnode.events[key1], false) | ||
if (vnode.events[key2] === callback) return | ||
if (vnode.events[key2] != null) element.removeEventListener(eventName, vnode.events[key2], false) | ||
if (typeof value === "function") { | ||
vnode.events[key1] = callback | ||
element.addEventListener(eventName, vnode.events[key1], false) | ||
vnode.events[key2] = callback | ||
element.addEventListener(eventName, vnode.events[key2], false) | ||
} | ||
@@ -885,3 +901,3 @@ } | ||
var active = $doc.activeElement | ||
// First time rendering into a node clears it out | ||
// First time0 rendering into a node clears it out | ||
if (dom.vnodes == null) dom.textContent = "" | ||
@@ -896,4 +912,3 @@ if (!(vnodes instanceof Array)) vnodes = [vnodes] | ||
} | ||
var renderService = _13(window) | ||
var throttle = function(callback1) { | ||
function throttle(callback) { | ||
//60fps translates to 16.6ms, round it down since setTimeout requires int | ||
@@ -903,7 +918,7 @@ var time = 16 | ||
var timeout = typeof requestAnimationFrame === "function" ? requestAnimationFrame : setTimeout | ||
return function(synchronous) { | ||
return function() { | ||
var now = Date.now() | ||
if (synchronous === true || last === 0 || now - last >= time) { | ||
if (last === 0 || now - last >= time) { | ||
last = now | ||
callback1() | ||
callback() | ||
} | ||
@@ -913,3 +928,3 @@ else if (pending === null) { | ||
pending = null | ||
callback1() | ||
callback() | ||
last = Date.now() | ||
@@ -920,21 +935,31 @@ }, time - (now - last)) | ||
} | ||
var autoredraw = function(root, renderer, pubsub, callback0) { | ||
var run1 = throttle(callback0) | ||
if (renderer != null) { | ||
renderer.setEventCallback(function(e) { | ||
if (e.redraw !== false) pubsub.publish() | ||
}) | ||
var _11 = function($window) { | ||
var renderService = coreRenderer($window) | ||
renderService.setEventCallback(function(e) { | ||
if (e.redraw !== false) redraw() | ||
}) | ||
var callbacks = [] | ||
function subscribe(key1, callback) { | ||
unsubscribe(key1) | ||
callbacks.push(key1, throttle(callback)) | ||
} | ||
if (pubsub != null) { | ||
if (root.redraw) pubsub.unsubscribe(root.redraw) | ||
pubsub.subscribe(run1) | ||
function unsubscribe(key1) { | ||
var index = callbacks.indexOf(key1) | ||
if (index > -1) callbacks.splice(index, 2) | ||
} | ||
return root.redraw = run1 | ||
function redraw() { | ||
for (var i = 1; i < callbacks.length; i += 2) { | ||
callbacks[i]() | ||
} | ||
} | ||
return {subscribe: subscribe, unsubscribe: unsubscribe, redraw: redraw, render: renderService.render} | ||
} | ||
var _17 = function(renderer, pubsub) { | ||
var redrawService = _11(window) | ||
requestService.setCompletionCallback(redrawService.redraw) | ||
var _16 = function(redrawService0) { | ||
return function(root, component) { | ||
if (component === null) { | ||
renderer.render(root, []) | ||
pubsub.unsubscribe(root.redraw) | ||
delete root.redraw | ||
redrawService0.render(root, []) | ||
redrawService0.unsubscribe(root) | ||
return | ||
@@ -944,10 +969,12 @@ } | ||
if (component.view == null) throw new Error("m.mount(element, component) expects a component, not a vnode") | ||
var run0 = autoredraw(root, renderer, pubsub, function() { | ||
renderer.render(root, Vnode(component, undefined, undefined, undefined, undefined, undefined)) | ||
}) | ||
run0() | ||
var run0 = function() { | ||
redrawService0.render(root, Vnode(component)) | ||
} | ||
redrawService0.subscribe(root, run0) | ||
redrawService0.redraw() | ||
} | ||
} | ||
m.mount = _17(renderService, redrawService) | ||
var mount = m.mount | ||
m.mount = _16(redrawService) | ||
var Promise = PromisePolyfill | ||
var parseQueryString = function(string) { | ||
@@ -959,9 +986,9 @@ if (string === "" || string == null) return {} | ||
var entry = entries[i].split("=") | ||
var key3 = decodeURIComponent(entry[0]) | ||
var key5 = decodeURIComponent(entry[0]) | ||
var value = entry.length === 2 ? decodeURIComponent(entry[1]) : "" | ||
if (value === "true") value = true | ||
else if (value === "false") value = false | ||
var levels = key3.split(/\]\[?|\[/) | ||
var levels = key5.split(/\]\[?|\[/) | ||
var cursor = data0 | ||
if (key3.indexOf("[") > -1) levels.pop() | ||
if (key5.indexOf("[") > -1) levels.pop() | ||
for (var j = 0; j < levels.length; j++) { | ||
@@ -972,5 +999,5 @@ var level = levels[j], nextLevel = levels[j + 1] | ||
if (level === "") { | ||
var key3 = levels.slice(0, j).join() | ||
if (counters[key3] == null) counters[key3] = 0 | ||
level = counters[key3]++ | ||
var key5 = levels.slice(0, j).join() | ||
if (counters[key5] == null) counters[key5] = 0 | ||
level = counters[key5]++ | ||
} | ||
@@ -988,5 +1015,3 @@ if (cursor[level] == null) { | ||
var callAsync0 = typeof setImmediate === "function" ? setImmediate : setTimeout | ||
var prefix1 = "#!" | ||
function setPrefix(value) {prefix1 = value} | ||
function normalize(fragment0) { | ||
function normalize1(fragment0) { | ||
var data = $window.location[fragment0].replace(/(?:%[a-f89][a-f0-9])+/gim, decodeURIComponent) | ||
@@ -997,3 +1022,3 @@ if (fragment0 === "pathname" && data[0] !== "/") data = "/" + data | ||
var asyncId | ||
function debounceAsync(f) { | ||
function debounceAsync(callback0) { | ||
return function() { | ||
@@ -1003,3 +1028,3 @@ if (asyncId != null) return | ||
asyncId = null | ||
f() | ||
callback0() | ||
}) | ||
@@ -1015,23 +1040,24 @@ } | ||
var queryParams = parseQueryString(path.slice(queryIndex + 1, queryEnd)) | ||
for (var key2 in queryParams) queryData[key2] = queryParams[key2] | ||
for (var key4 in queryParams) queryData[key4] = queryParams[key4] | ||
} | ||
if (hashIndex > -1) { | ||
var hashParams = parseQueryString(path.slice(hashIndex + 1)) | ||
for (var key2 in hashParams) hashData[key2] = hashParams[key2] | ||
for (var key4 in hashParams) hashData[key4] = hashParams[key4] | ||
} | ||
return path.slice(0, pathEnd) | ||
} | ||
function getPath() { | ||
var type2 = prefix1.charAt(0) | ||
var router = {prefix: "#!"} | ||
router.getPath = function() { | ||
var type2 = router.prefix.charAt(0) | ||
switch (type2) { | ||
case "#": return normalize("hash").slice(prefix1.length) | ||
case "?": return normalize("search").slice(prefix1.length) + normalize("hash") | ||
default: return normalize("pathname").slice(prefix1.length) + normalize("search") + normalize("hash") | ||
case "#": return normalize1("hash").slice(router.prefix.length) | ||
case "?": return normalize1("search").slice(router.prefix.length) + normalize1("hash") | ||
default: return normalize1("pathname").slice(router.prefix.length) + normalize1("search") + normalize1("hash") | ||
} | ||
} | ||
function setPath(path, data, options) { | ||
router.setPath = function(path, data, options) { | ||
var queryData = {}, hashData = {} | ||
path = parsePath(path, queryData, hashData) | ||
if (data != null) { | ||
for (var key2 in data) queryData[key2] = data[key2] | ||
for (var key4 in data) queryData[key4] = data[key4] | ||
path = path.replace(/:([^\/]+)/g, function(match2, token) { | ||
@@ -1047,15 +1073,11 @@ delete queryData[token] | ||
if (supportsPushState) { | ||
if (options && options.replace) $window.history.replaceState(null, null, prefix1 + path) | ||
else $window.history.pushState(null, null, prefix1 + path) | ||
if (options && options.replace) $window.history.replaceState(null, null, router.prefix + path) | ||
else $window.history.pushState(null, null, router.prefix + path) | ||
$window.onpopstate() | ||
} | ||
else $window.location.href = prefix1 + path | ||
else $window.location.href = router.prefix + path | ||
} | ||
function defineRoutes(routes, resolve0, reject) { | ||
if (supportsPushState) $window.onpopstate = debounceAsync(resolveRoute) | ||
else if (prefix1.charAt(0) === "#") $window.onhashchange = resolveRoute | ||
resolveRoute() | ||
router.defineRoutes = function(routes, resolve, reject) { | ||
function resolveRoute() { | ||
var path = getPath() | ||
var path = router.getPath() | ||
var params = {} | ||
@@ -1073,3 +1095,3 @@ var pathname = parsePath(path, params, params) | ||
} | ||
resolve0(routes[route0], params, path, route0) | ||
resolve(routes[route0], params, path, route0) | ||
}) | ||
@@ -1081,7 +1103,51 @@ return | ||
} | ||
return resolveRoute | ||
if (supportsPushState) $window.onpopstate = debounceAsync(resolveRoute) | ||
else if (router.prefix.charAt(0) === "#") $window.onhashchange = resolveRoute | ||
resolveRoute() | ||
} | ||
function link(vnode2) { | ||
vnode2.dom.setAttribute("href", prefix1 + vnode2.attrs.href) | ||
vnode2.dom.onclick = function(e) { | ||
return router | ||
} | ||
var _20 = function($window, redrawService0) { | ||
var routeService = coreRouter($window) | ||
var identity = function(v) {return v} | ||
var render1, component, attrs3, currentPath, updatePending = false | ||
var route = function(root, defaultRoute, routes) { | ||
if (root == null) throw new Error("Ensure the DOM element that was passed to `m.route` is not undefined") | ||
var update = function(routeResolver, comp, params, path) { | ||
component = comp != null && typeof comp.view === "function" ? comp : "div", attrs3 = params, currentPath = path, updatePending = false | ||
render1 = (routeResolver.render || identity).bind(routeResolver) | ||
run1() | ||
} | ||
var run1 = function() { | ||
if (render1 != null) redrawService0.render(root, render1(Vnode(component, attrs3.key, attrs3))) | ||
} | ||
var bail = function() { | ||
routeService.setPath(defaultRoute) | ||
} | ||
routeService.defineRoutes(routes, function(payload, params, path) { | ||
if (payload.view) update({}, payload, params, path) | ||
else { | ||
if (payload.onmatch) { | ||
updatePending = true | ||
Promise.resolve(payload.onmatch(params, path)).then(function(resolved) { | ||
if (updatePending) update(payload, resolved, params, path) | ||
}, bail) | ||
} | ||
else update(payload, "div", params, path) | ||
} | ||
}, bail) | ||
redrawService0.subscribe(root, run1) | ||
} | ||
route.set = function(path, data, options) { | ||
if (updatePending) options = {replace: true} | ||
updatePending = false | ||
routeService.setPath(path, data, options) | ||
} | ||
route.get = function() {return currentPath} | ||
route.prefix = function(prefix0) {routeService.prefix = prefix0} | ||
route.link = function(vnode1) { | ||
vnode1.dom.setAttribute("href", routeService.prefix + vnode1.attrs.href) | ||
vnode1.dom.onclick = function(e) { | ||
if (e.ctrlKey || e.metaKey || e.shiftKey || e.which === 2) return | ||
@@ -1091,61 +1157,17 @@ e.preventDefault() | ||
var href = this.getAttribute("href") | ||
if (href.indexOf(prefix1) === 0) href = href.slice(prefix1.length) | ||
setPath(href, undefined, undefined) | ||
if (href.indexOf(routeService.prefix) === 0) href = href.slice(routeService.prefix.length) | ||
route.set(href, undefined, undefined) | ||
} | ||
} | ||
return {setPrefix: setPrefix, getPath: getPath, setPath: setPath, defineRoutes: defineRoutes, link: link} | ||
} | ||
var _23 = function($window, mount0) { | ||
var router = coreRouter($window) | ||
var currentResolve, currentComponent, currentRender, currentArgs, currentPath | ||
var RouteComponent = {view: function() { | ||
return [currentRender(Vnode(currentComponent, null, currentArgs, undefined, undefined, undefined))] | ||
}} | ||
function defaultRender(vnode1) { | ||
return vnode1 | ||
} | ||
var route = function(root, defaultRoute, routes) { | ||
currentComponent = "div" | ||
currentRender = defaultRender | ||
currentArgs = null | ||
mount0(root, RouteComponent) | ||
router.defineRoutes(routes, function(payload, args0, path) { | ||
var isResolver = typeof payload.view !== "function" | ||
var render1 = defaultRender | ||
var resolve = currentResolve = function (component) { | ||
if (resolve !== currentResolve) return | ||
currentResolve = null | ||
currentComponent = component != null ? component : isResolver ? "div" : payload | ||
currentRender = render1 | ||
currentArgs = args0 | ||
currentPath = path | ||
root.redraw(true) | ||
} | ||
var onmatch = function() { | ||
resolve() | ||
} | ||
if (isResolver) { | ||
if (typeof payload.render === "function") render1 = payload.render.bind(payload) | ||
if (typeof payload.onmatch === "function") onmatch = payload.onmatch | ||
} | ||
onmatch.call(payload, resolve, args0, path) | ||
}, function() { | ||
router.setPath(defaultRoute, null, {replace: true}) | ||
}) | ||
} | ||
route.link = router.link | ||
route.prefix = router.setPrefix | ||
route.set = router.setPath | ||
route.get = function() {return currentPath} | ||
return route | ||
} | ||
m.route = _23(window, mount) | ||
m.withAttr = function(attrName, callback2, context) { | ||
m.route = _20(window, redrawService) | ||
m.withAttr = function(attrName, callback1, context) { | ||
return function(e) { | ||
return callback2.call(context || this, attrName in e.currentTarget ? e.currentTarget[attrName] : e.currentTarget.getAttribute(attrName)) | ||
return callback1.call(context || this, attrName in e.currentTarget ? e.currentTarget[attrName] : e.currentTarget.getAttribute(attrName)) | ||
} | ||
} | ||
m.render = renderService.render | ||
m.redraw = redrawService.publish | ||
var _28 = coreRenderer(window) | ||
m.render = _28.render | ||
m.redraw = redrawService.redraw | ||
m.request = requestService.request | ||
@@ -1155,5 +1177,5 @@ m.jsonp = requestService.jsonp | ||
m.buildQueryString = buildQueryString | ||
m.version = "1.0.0-rc.4" | ||
m.version = "1.0.0-rc.6" | ||
if (typeof module !== "undefined") module["exports"] = m | ||
else window.m = m | ||
} |
@@ -1,40 +0,41 @@ | ||
new function(){function m(a,b,k,d,l,h){return{tag:a,key:b,attrs:k,children:d,text:l,dom:h,domSize:void 0,state:{},events:void 0,instance:void 0,skip:!1}}function t(a){if(null==a||"string"!==typeof a&&null==a.view)throw Error("The selector must be either a string or a component.");if("string"===typeof a&&void 0===G[a]){for(var b,k,d=[],l={};b=N.exec(a);){var h=b[1],u=b[2];""===h&&""!==u?k=u:"#"===h?l.id=u:"."===h?d.push(u):"["===b[3][0]&&((h=b[6])&&(h=h.replace(/\\(["'])/g,"$1").replace(/\\\\/g,"\\")), | ||
l[b[4]]=h||!0)}0<d.length&&(l.className=d.join(" "));G[a]=function(a,b){var d=!1,h,f,w=a.className||a["class"],p;for(p in l)a[p]=l[p];void 0!==w&&(void 0!==a["class"]&&(a["class"]=void 0,a.className=w),void 0!==l.className&&(a.className=l.className+" "+w));for(p in a)if("key"!==p){d=!0;break}b instanceof Array&&1==b.length&&null!=b[0]&&"#"===b[0].tag?f=b[0].children:h=b;return m(k||"div",a.key,d?a:void 0,h,f,void 0)}}var q;null!=arguments[1]&&("object"!==typeof arguments[1]||void 0!==arguments[1].tag|| | ||
arguments[1]instanceof Array)?d=1:(q=arguments[1],d=2);if(arguments.length===d+1)b=arguments[d]instanceof Array?arguments[d]:[arguments[d]];else for(b=[];d<arguments.length;d++)b.push(arguments[d]);return"string"===typeof a?G[a](q||{},m.normalizeChildren(b)):m(a,q&&q.key,q||{},m.normalizeChildren(b),void 0,void 0)}m.normalize=function(a){return a instanceof Array?m("[",void 0,void 0,m.normalizeChildren(a),void 0,void 0):null!=a&&"object"!==typeof a?m("#",void 0,void 0,a,void 0,void 0):a};m.normalizeChildren= | ||
function(a){for(var b=0;b<a.length;b++)a[b]=m.normalize(a[b]);return a};var N=/(?:(^|#|\.)([^#\.\[\]]+))|(\[(.+?)(?:\s*=\s*("|'|)((?:\\["'\]]|.)*?)\5)?\])/g,G={};t.trust=function(a){null==a&&(a="");return m("<",void 0,void 0,a,void 0,void 0)};t.fragment=function(a,b){return m("[",a.key,a,m.normalizeChildren(b),void 0,void 0)};var x=function(a){function b(a,b){return function w(p){var n;try{if(!b||null==p||"object"!==typeof p&&"function"!==typeof p||"function"!==typeof(n=p.then))m(function(){b||0!== | ||
a.length||console.error("Possible unhandled promise rejection:",p);for(var d=0;d<a.length;d++)a[d](p);l.length=0;h.length=0;r.state=b;r.retry=function(){w(p)}});else{if(p===d)throw new TypeError("Promise can't be resolved w/ itself");k(n.bind(p))}}catch(E){q(E)}}}function k(a){function b(a){return function(b){0<f++||a(b)}}var f=0,d=b(q);try{a(b(u),d)}catch(p){d(p)}}if(!(this instanceof x))throw Error("Promise must be called with `new`");if("function"!==typeof a)throw new TypeError("executor must be a function"); | ||
var d=this,l=[],h=[],u=b(l,!0),q=b(h,!1),r=d._instance={resolvers:l,rejectors:h},m="function"===typeof setImmediate?setImmediate:setTimeout;k(a)};x.prototype.then=function(a,b){function k(a,b,k,n){b.push(function(b){if("function"!==typeof a)k(b);else try{l(a(b))}catch(f){h&&h(f)}});"function"===typeof d.retry&&n===d.state&&d.retry()}var d=this._instance,l,h,u=new x(function(a,b){l=a;h=b});k(a,d.resolvers,l,!0);k(b,d.rejectors,h,!1);return u};x.prototype["catch"]=function(a){return this.then(null, | ||
a)};x.resolve=function(a){return a instanceof x?a:new x(function(b){b(a)})};x.reject=function(a){return new x(function(b,k){k(a)})};x.all=function(a){return new x(function(b,k){var d=a.length,l=0,h=[];if(0===a.length)b([]);else for(var u=0;u<a.length;u++)(function(u){function r(a){l++;h[u]=a;l===d&&b(h)}null==a[u]||"object"!==typeof a[u]&&"function"!==typeof a[u]||"function"!==typeof a[u].then?r(a[u]):a[u].then(r,k)})(u)})};x.race=function(a){return new x(function(b,k){for(var d=0;d<a.length;d++)a[d].then(b, | ||
k)})};"undefined"===typeof Promise&&("undefined"!==typeof window?window.Promise=x:"undefined"!==typeof global&&(global.Promise=x));var C=function(a){function b(a,d){if(d instanceof Array)for(var h=0;h<d.length;h++)b(a+"["+h+"]",d[h]);else if("[object Object]"===Object.prototype.toString.call(d))for(h in d)b(a+"["+h+"]",d[h]);else k.push(encodeURIComponent(a)+(null!=d&&""!==d?"="+encodeURIComponent(d):""))}if("[object Object]"!==Object.prototype.toString.call(a))return"";var k=[],d;for(d in a)b(d, | ||
a[d]);return k.join("&")},H=function(a,b){function k(){0===--n&&"function"===typeof v&&v()}function d(a){var f=a.then;a.then=function(){n++;var b=f.apply(a,arguments);b.then(k,function(a){k();throw a;});return d(b)};return a}function l(a,b){if(null==b)return a;for(var f=a.match(/:[^\/]+/gi)||[],d=0;d<f.length;d++){var h=f[d].slice(1);null!=b[h]&&(a=a.replace(f[d],b[h]),delete b[h])}return a}function h(a,b){var f=C(b);if(""!==f){var d=0>a.indexOf("?")?"?":"&";a+=d+f}return a}function u(a){try{return""!== | ||
a?JSON.parse(a):null}catch(w){throw Error(a);}}function q(a){return a.responseText}function r(a,b){if("function"===typeof a)if(b instanceof Array)for(var d=0;d<b.length;d++)b[d]=new a(b[d]);else return new a(b);return b}var m=0,n=0,v;return{request:function(f,k){return d(new b(function(b,d){if("string"===typeof f){var n=f;f=k||{};null==f.url&&(f.url=n)}null==f.method&&(f.method="GET");f.method=f.method.toUpperCase();n="boolean"===typeof f.useBody?f.useBody:"GET"!==f.method&&"TRACE"!==f.method;"function"!== | ||
typeof f.serialize&&(f.serialize="undefined"!==typeof FormData&&f.data instanceof FormData?function(a){return a}:JSON.stringify);"function"!==typeof f.deserialize&&(f.deserialize=u);"function"!==typeof f.extract&&(f.extract=q);f.url=l(f.url,f.data);n?f.data=f.serialize(f.data):f.url=h(f.url,f.data);var p=new a.XMLHttpRequest;p.open(f.method,f.url,"boolean"===typeof f.async?f.async:!0,"string"===typeof f.user?f.user:void 0,"string"===typeof f.password?f.password:void 0);f.serialize===JSON.stringify&& | ||
n&&p.setRequestHeader("Content-Type","application/json; charset=utf-8");f.deserialize===u&&p.setRequestHeader("Accept","application/json, text/*");"function"===typeof f.config&&(p=f.config(p,f)||p);p.onreadystatechange=function(){if(4===p.readyState)try{var a=f.extract!==q?f.extract(p,f):f.deserialize(f.extract(p,f));if(200<=p.status&&300>p.status||304===p.status)b(r(f.type,a));else{var h=Error(p.responseText),k;for(k in a)h[k]=a[k];d(h)}}catch(F){d(F)}};n&&null!=f.data?p.send(f.data):p.send()}))}, | ||
jsonp:function(f){return d(new b(function(b,d){var p=f.callbackName||"_mithril_"+Math.round(1E16*Math.random())+"_"+m++,k=a.document.createElement("script");a[p]=function(d){k.parentNode.removeChild(k);b(r(f.type,d));delete a[p]};k.onerror=function(){k.parentNode.removeChild(k);d(Error("JSONP request failed"));delete a[p]};null==f.data&&(f.data={});f.url=l(f.url,f.data);f.data[f.callbackKey||"callback"]=p;k.src=h(f.url,f.data);a.document.documentElement.appendChild(k)}))},setCompletionCallback:function(a){v= | ||
a}}}(window,"undefined"!==typeof Promise?Promise:x),I=function(){var a=[];return{subscribe:a.push.bind(a),unsubscribe:function(b){b=a.indexOf(b);-1<b&&a.splice(b,1)},publish:function(){for(var b=0;b<a.length;b++)a[b].apply(this,arguments)}}}();H.setCompletionCallback(I.publish);var M=function(a){function b(c,g,a,b,d,f,h){for(;a<b;a++){var e=g[a];null!=e&&r(c,k(e,d,h),f)}}function k(c,g,a){var e=c.tag;null!=c.attrs&&t(c.attrs,c,g);if("string"===typeof e)switch(e){case "#":return c.dom=A.createTextNode(c.children); | ||
case "<":return d(c);case "[":var f=A.createDocumentFragment();null!=c.children&&(e=c.children,b(f,e,0,e.length,g,null,a));c.dom=f.firstChild;c.domSize=f.childNodes.length;return f;default:var h=c.tag;switch(c.tag){case "svg":a="http://www.w3.org/2000/svg";break;case "math":a="http://www.w3.org/1998/Math/MathML"}var n=(e=c.attrs)&&e.is,h=a?n?A.createElementNS(a,h,{is:n}):A.createElementNS(a,h):n?A.createElement(h,{is:n}):A.createElement(h);c.dom=h;if(null!=e)for(f in n=a,e)p(c,f,null,e[f],n);null!= | ||
c.attrs&&null!=c.attrs.contenteditable?x(c):(null!=c.text&&(""!==c.text?h.textContent=c.text:c.children=[m("#",void 0,void 0,c.text,void 0,void 0)]),null!=c.children&&(f=c.children,b(h,f,0,f.length,g,null,a),g=c.attrs,"select"===c.tag&&null!=g&&("value"in g&&p(c,"value",null,g.value,void 0),"selectedIndex"in g&&p(c,"selectedIndex",null,g.selectedIndex,void 0))));return h}else{c.state||(c.state={});O(c.state,c.tag);f=c.tag.view;if(null!=f.reentrantLock)c=F;else if(f.reentrantLock=!0,t(c.tag,c,g),c.instance= | ||
m.normalize(f.call(c.state,c)),f.reentrantLock=null,null!=c.instance){if(c.instance===c)throw Error("A view cannot return the vnode it received as arguments");g=k(c.instance,g,a);c.dom=c.instance.dom;c.domSize=null!=c.dom?c.instance.domSize:0;c=g}else c.domSize=0,c=F;return c}}function d(c){var g={caption:"table",thead:"table",tbody:"table",tfoot:"table",tr:"tbody",th:"tr",td:"tr",colgroup:"table",col:"colgroup"}[(c.children.match(/^\s*?<(\w+)/im)||[])[1]]||"div",g=A.createElement(g);g.innerHTML= | ||
c.children;c.dom=g.firstChild;c.domSize=g.childNodes.length;c=A.createDocumentFragment();for(var a;a=g.firstChild;)c.appendChild(a);return c}function l(c,a,e,f,d,p){if(a!==e&&(null!=a||null!=e))if(null==a)b(c,e,0,e.length,f,d,void 0);else if(null==e)n(a,0,a.length,e);else{var g;a:{if(null!=a.pool&&Math.abs(a.pool.length-e.length)<=Math.abs(a.length-e.length)&&(g=e[0]&&e[0].children&&e[0].children.length||0,Math.abs((a.pool[0]&&a.pool[0].children&&a.pool[0].children.length||0)-g)<=Math.abs((a[0]&& | ||
a[0].children&&a[0].children.length||0)-g))){g=!0;break a}g=!1}g&&(a=a.concat(a.pool));if(a.length===e.length&&null!=e[0]&&null==e[0].key)for(var l=0;l<a.length;l++)a[l]===e[l]||null==a[l]&&null==e[l]||(null==a[l]?r(c,k(e[l],f,p),q(a,l+1,d)):null==e[l]?n(a,l,l+1,e):h(c,a[l],e[l],f,q(a,l+1,d),g,p),g&&a[l].tag===e[l].tag&&r(c,u(a[l]),q(a,l+1,d)));else{for(var z=l=0,v=a.length-1,B=e.length-1,w;v>=l&&B>=z;){var y=a[l],m=e[z];if(y!==m||g)if(null!=y&&null!=m&&y.key===m.key)l++,z++,h(c,y,m,f,q(a,l,d),g, | ||
p),g&&y.tag===m.tag&&r(c,u(y),d);else if(y=a[v],y!==m||g)if(null!=y&&null!=m&&y.key===m.key)h(c,y,m,f,q(a,v+1,d),g,p),(g||z<B)&&r(c,u(y),q(a,l,d)),v--,z++;else break;else v--,z++;else l++,z++}for(;v>=l&&B>=z;){y=a[v];m=e[B];if(y!==m||g)if(null!=y&&null!=m&&y.key===m.key)h(c,y,m,f,q(a,v+1,d),g,p),g&&y.tag===m.tag&&r(c,u(y),d),null!=y.dom&&(d=y.dom),v--;else{if(!w){w=a;var y=v,D={},t;for(t=0;t<y;t++){var x=w[t];null!=x&&(x=x.key,null!=x&&(D[x]=t))}w=D}null!=m&&(y=w[m.key],null!=y?(D=a[y],h(c,D,m,f, | ||
q(a,v+1,d),g,p),r(c,u(D),d),a[y].skip=!0,null!=D.dom&&(d=D.dom)):(m=k(m,f,void 0),r(c,m,d),d=m))}else v--;B--;if(B<z)break}b(c,e,z,B+1,f,d,p);n(a,l,v+1,e)}}}function h(a,g,e,b,n,v,w){var c=g.tag;if(c===e.tag){e.state=g.state;e.events=g.events;var z;var B;null!=e.attrs&&"function"===typeof e.attrs.onbeforeupdate&&(z=e.attrs.onbeforeupdate.call(e.state,e,g));"string"!==typeof e.tag&&"function"===typeof e.tag.onbeforeupdate&&(B=e.tag.onbeforeupdate.call(e.state,e,g));void 0===z&&void 0===B||z||B?z=!1: | ||
(e.dom=g.dom,e.domSize=g.domSize,e.instance=g.instance,z=!0);if(!z)if(null!=e.attrs&&L(e.attrs,e,b,v),"string"===typeof c)switch(c){case "#":g.children.toString()!==e.children.toString()&&(g.dom.nodeValue=e.children);e.dom=g.dom;break;case "<":g.children!==e.children?(u(g),r(a,d(e),n)):(e.dom=g.dom,e.domSize=g.domSize);break;case "[":l(a,g.children,e.children,b,n,w);g=0;b=e.children;e.dom=null;if(null!=b){for(var q=0;q<b.length;q++)a=b[q],null!=a&&null!=a.dom&&(null==e.dom&&(e.dom=a.dom),g+=a.domSize|| | ||
1);1!==g&&(e.domSize=g)}break;default:a=w;n=e.dom=g.dom;switch(e.tag){case "svg":a="http://www.w3.org/2000/svg";break;case "math":a="http://www.w3.org/1998/Math/MathML"}"textarea"===e.tag&&(null==e.attrs&&(e.attrs={}),null!=e.text&&(e.attrs.value=e.text,e.text=void 0));v=g.attrs;w=e.attrs;c=a;if(null!=w)for(q in w)p(e,q,v&&v[q],w[q],c);if(null!=v)for(q in v)null!=w&&q in w||("className"===q&&(q="class"),"o"!==q[0]||"n"!==q[1]||K(q)?"key"!==q&&e.dom.removeAttribute(q):E(e,q,void 0));null!=e.attrs&& | ||
null!=e.attrs.contenteditable?x(e):null!=g.text&&null!=e.text&&""!==e.text?g.text.toString()!==e.text.toString()&&(g.dom.firstChild.nodeValue=e.text):(null!=g.text&&(g.children=[m("#",void 0,void 0,g.text,void 0,g.dom.firstChild)]),null!=e.text&&(e.children=[m("#",void 0,void 0,e.text,void 0,void 0)]),l(n,g.children,e.children,b,null,a))}else e.instance=m.normalize(e.tag.view.call(e.state,e)),L(e.tag,e,b,v),null!=e.instance?(null==g.instance?r(a,k(e.instance,b,w),n):h(a,g.instance,e.instance,b,n, | ||
v,w),e.dom=e.instance.dom,e.domSize=e.instance.domSize):null!=g.instance?(f(g.instance,null),e.dom=void 0,e.domSize=0):(e.dom=g.dom,e.domSize=g.domSize)}else f(g,null),r(a,k(e,b,w),n)}function u(a){var c=a.domSize;if(null!=c||null==a.dom){var e=A.createDocumentFragment();if(0<c){for(a=a.dom;--c;)e.appendChild(a.nextSibling);e.insertBefore(a,e.firstChild)}return e}return a.dom}function q(a,g,e){for(;g<a.length;g++)if(null!=a[g]&&null!=a[g].dom)return a[g].dom;return e}function r(a,g,e){e&&e.parentNode? | ||
a.insertBefore(g,e):a.appendChild(g)}function x(a){var c=a.children;if(null!=c&&1===c.length&&"<"===c[0].tag)c=c[0].children,a.dom.innerHTML!==c&&(a.dom.innerHTML=c);else if(null!=c||null!=a.text)throw Error("Child node of a contenteditable must be trusted");}function n(a,g,e,b){for(;g<e;g++){var c=a[g];null!=c&&(c.skip?c.skip=!1:f(c,b))}}function v(a){var c=!1;return function(){c||(c=!0,a())}}function f(a,g){function c(){if(++d===b&&(w(a),a.dom)){var c=a.domSize||1;if(1<c)for(var e=a.dom;--c;){var f= | ||
e.nextSibling,h=f.parentNode;null!=h&&h.removeChild(f)}c=a.dom;e=c.parentNode;null!=e&&e.removeChild(c);if(c=null!=g&&null==a.domSize)c=a.attrs,c=!(null!=c&&(c.oncreate||c.onupdate||c.onbeforeremove||c.onremove));c&&"string"===typeof a.tag&&(g.pool?g.pool.push(a):g.pool=[a])}}var b=1,d=0;a.attrs&&a.attrs.onbeforeremove&&(b++,a.attrs.onbeforeremove.call(a.state,a,v(c)));"string"!==typeof a.tag&&a.tag.onbeforeremove&&(b++,a.tag.onbeforeremove.call(a.state,a,v(c)));c()}function w(a){a.attrs&&a.attrs.onremove&& | ||
a.attrs.onremove.call(a.state,a);"string"!==typeof a.tag&&a.tag.onremove&&a.tag.onremove.call(a.state,a);if(null!=a.instance)w(a.instance);else if(a=a.children,a instanceof Array)for(var c=0;c<a.length;c++){var e=a[c];null!=e&&w(e)}}function p(a,g,e,b,d){var c=a.dom;if("key"!==g&&(e!==b||"value"===g||"checked"===g||"selectedIndex"===g||"selected"===g&&a.dom===A.activeElement||"object"===typeof b)&&"undefined"!==typeof b&&!K(g)){var f=g.indexOf(":");if(-1<f&&"xlink"===g.substr(0,f))c.setAttributeNS("http://www.w3.org/1999/xlink", | ||
g.slice(f+1),b);else if("o"===g[0]&&"n"===g[1]&&"function"===typeof b)E(a,g,b);else if("style"===g)if(a=e,a===b&&(c.style.cssText="",a=null),null==b)c.style.cssText="";else if("string"===typeof b)c.style.cssText=b;else{"string"===typeof a&&(c.style.cssText="");for(var h in b)c.style[h]=b[h];if(null!=a&&"string"!==typeof a)for(h in a)h in b||(c.style[h]="")}else if(g in c&&"href"!==g&&"list"!==g&&"form"!==g&&"width"!==g&&"height"!==g&&void 0===d){if("input"!==a.tag||"value"!==g||a.dom.value!==b||a.dom!== | ||
A.activeElement)c[g]=b}else"boolean"===typeof b?b?c.setAttribute(g,""):c.removeAttribute(g):c.setAttribute("className"===g?"class":g,b)}}function K(a){return"oninit"===a||"oncreate"===a||"onupdate"===a||"onremove"===a||"onbeforeremove"===a||"onbeforeupdate"===a}function E(a,b,e){var c=a.dom,g=function(a){var b=e.call(c,a);"function"===typeof C&&C.call(c,a);return b};if(b in c)c[b]="function"===typeof e?g:null;else{var d=b.slice(2);void 0===a.events&&(a.events={});null!=a.events[b]&&c.removeEventListener(d, | ||
a.events[b],!1);"function"===typeof e&&(a.events[b]=g,c.addEventListener(d,a.events[b],!1))}}function t(a,b,e){"function"===typeof a.oninit&&a.oninit.call(b.state,b);"function"===typeof a.oncreate&&e.push(a.oncreate.bind(b.state,b))}function L(a,b,e,d){d?t(a,b,e):"function"===typeof a.onupdate&&e.push(a.onupdate.bind(b.state,b))}function O(a,b){Object.keys(b).forEach(function(c){a[c]=b[c]})}var A=a.document,F=A.createDocumentFragment(),C;return{render:function(a,b){if(!a)throw Error("Ensure the DOM element being passed to m.route/m.mount/m.render is not undefined."); | ||
var c=[],d=A.activeElement;null==a.vnodes&&(a.textContent="");b instanceof Array||(b=[b]);l(a,a.vnodes,m.normalizeChildren(b),c,null,void 0);a.vnodes=b;for(var f=0;f<c.length;f++)c[f]();A.activeElement!==d&&d.focus()},setEventCallback:function(a){return C=a}}}(window),P=function(a){var b=0,k=null,d="function"===typeof requestAnimationFrame?requestAnimationFrame:setTimeout;return function(l){var h=Date.now();!0===l||0===b||16<=h-b?(b=h,a()):null===k&&(k=d(function(){k=null;a();b=Date.now()},16-(h- | ||
b)))}},Q=function(a,b,k,d){d=P(d);null!=b&&b.setEventCallback(function(a){!1!==a.redraw&&k.publish()});null!=k&&(a.redraw&&k.unsubscribe(a.redraw),k.subscribe(d));return a.redraw=d};t.mount=function(a,b){return function(k,d){if(null===d)a.render(k,[]),b.unsubscribe(k.redraw),delete k.redraw;else{if(null==d.view)throw Error("m.mount(element, component) expects a component, not a vnode");Q(k,a,b,function(){a.render(k,m(d,void 0,void 0,void 0,void 0,void 0))})()}}}(M,I);var J=function(a){if(""===a|| | ||
null==a)return{};"?"===a.charAt(0)&&(a=a.slice(1));a=a.split("&");for(var b={},k={},d=0;d<a.length;d++){var l=a[d].split("="),h=decodeURIComponent(l[0]),l=2===l.length?decodeURIComponent(l[1]):"";"true"===l?l=!0:"false"===l&&(l=!1);var m=h.split(/\]\[?|\[/),q=b;-1<h.indexOf("[")&&m.pop();for(var r=0;r<m.length;r++){var h=m[r],t=m[r+1],t=""==t||!isNaN(parseInt(t,10)),n=r===m.length-1;""===h&&(h=m.slice(0,r).join(),null==k[h]&&(k[h]=0),h=k[h]++);null==q[h]&&(q[h]=n?l:t?[]:{});q=q[h]}}return b},R=function(a){function b(b){var d= | ||
a.location[b].replace(/(?:%[a-f89][a-f0-9])+/gim,decodeURIComponent);"pathname"===b&&"/"!==d[0]&&(d="/"+d);return d}function k(a){return function(){null==t&&(t=q(function(){t=null;a()}))}}function d(a,b,d){var f=a.indexOf("?"),h=a.indexOf("#"),l=-1<f?f:-1<h?h:a.length;if(-1<f){var f=J(a.slice(f+1,-1<h?h:a.length)),k;for(k in f)b[k]=f[k]}if(-1<h)for(k in b=J(a.slice(h+1)),b)d[k]=b[k];return a.slice(0,l)}function l(){switch(r.charAt(0)){case "#":return b("hash").slice(r.length);case "?":return b("search").slice(r.length)+ | ||
b("hash");default:return b("pathname").slice(r.length)+b("search")+b("hash")}}function h(b,h,f){var k={},l={};b=d(b,k,l);if(null!=h){for(var n in h)k[n]=h[n];b=b.replace(/:([^\/]+)/g,function(a,b){delete k[b];return h[b]})}(n=C(k))&&(b+="?"+n);(l=C(l))&&(b+="#"+l);m?(f&&f.replace?a.history.replaceState(null,null,r+b):a.history.pushState(null,null,r+b),a.onpopstate()):a.location.href=r+b}var m="function"===typeof a.history.pushState,q="function"===typeof setImmediate?setImmediate:setTimeout,r="#!", | ||
t;return{setPrefix:function(a){r=a},getPath:l,setPath:h,defineRoutes:function(b,h,f){function n(){var a=l(),k={},m=d(a,k,k),n;for(n in b){var q=new RegExp("^"+n.replace(/:[^\/]+?\.{3}/g,"(.*?)").replace(/:[^\/]+/g,"([^\\/]+)")+"/?$");if(q.test(m)){m.replace(q,function(){for(var d=n.match(/:[^\/]+/g)||[],f=[].slice.call(arguments,1,-2),l=0;l<d.length;l++)k[d[l].replace(/:|\./g,"")]=decodeURIComponent(f[l]);h(b[n],k,a,n)});return}}f(a,k)}m?a.onpopstate=k(n):"#"===r.charAt(0)&&(a.onhashchange=n);n(); | ||
return n},link:function(a){a.dom.setAttribute("href",r+a.attrs.href);a.dom.onclick=function(a){a.ctrlKey||a.metaKey||a.shiftKey||2===a.which||(a.preventDefault(),a.redraw=!1,a=this.getAttribute("href"),0===a.indexOf(r)&&(a=a.slice(r.length)),h(a,void 0,void 0))}}}};t.route=function(a,b){function k(a){return a}var d=R(a),l,h,t,q,r,x={view:function(){return[t(m(h,null,q,void 0,void 0,void 0))]}},n=function(a,f,m){h="div";t=k;q=null;b(a,x);d.defineRoutes(m,function(b,d,f){var m="function"!==typeof b.view, | ||
n=k,p=l=function(k){p===l&&(l=null,h=null!=k?k:m?"div":b,t=n,q=d,r=f,a.redraw(!0))},u=function(){p()};m&&("function"===typeof b.render&&(n=b.render.bind(b)),"function"===typeof b.onmatch&&(u=b.onmatch));u.call(b,p,d,f)},function(){d.setPath(f,null,{replace:!0})})};n.link=d.link;n.prefix=d.setPrefix;n.set=d.setPath;n.get=function(){return r};return n}(window,t.mount);t.withAttr=function(a,b,k){return function(d){return b.call(k||this,a in d.currentTarget?d.currentTarget[a]:d.currentTarget.getAttribute(a))}}; | ||
t.render=M.render;t.redraw=I.publish;t.request=H.request;t.jsonp=H.jsonp;t.parseQueryString=J;t.buildQueryString=C;t.version="1.0.0-rc.4";"undefined"!==typeof module?module.exports=t:window.m=t}; | ||
new function(){function w(a,c,h,d,g,m){return{tag:a,key:c,attrs:h,children:d,text:g,dom:m,domSize:void 0,state:{},events:void 0,instance:void 0,skip:!1}}function z(a){if(null==a||"string"!==typeof a&&null==a.view)throw Error("The selector must be either a string or a component.");if("string"===typeof a&&void 0===K[a]){for(var c,h,d=[],g={};c=P.exec(a);){var m=c[1],l=c[2];""===m&&""!==l?h=l:"#"===m?g.id=l:"."===m?d.push(l):"["===c[3][0]&&((m=c[6])&&(m=m.replace(/\\(["'])/g,"$1").replace(/\\\\/g,"\\")), | ||
"class"===c[4]?d.push(m):g[c[4]]=m||!0)}0<d.length&&(g.className=d.join(" "));K[a]=function(a,c){var m=!1,b,p,d=a.className||a["class"],t;for(t in g)a[t]=g[t];void 0!==d&&(void 0!==a["class"]&&(a["class"]=void 0,a.className=d),void 0!==g.className&&(a.className=g.className+" "+d));for(t in a)if("key"!==t){m=!0;break}c instanceof Array&&1==c.length&&null!=c[0]&&"#"===c[0].tag?p=c[0].children:b=c;return w(h||"div",a.key,m?a:void 0,b,p,void 0)}}var n;null!=arguments[1]&&("object"!==typeof arguments[1]|| | ||
void 0!==arguments[1].tag||arguments[1]instanceof Array)?d=1:(n=arguments[1],d=2);if(arguments.length===d+1)c=arguments[d]instanceof Array?arguments[d]:[arguments[d]];else for(c=[];d<arguments.length;d++)c.push(arguments[d]);return"string"===typeof a?K[a](n||{},w.normalizeChildren(c)):w(a,n&&n.key,n||{},w.normalizeChildren(c),void 0,void 0)}function Q(a){var c=0,h=null,d="function"===typeof requestAnimationFrame?requestAnimationFrame:setTimeout;return function(){var g=Date.now();0===c||16<=g-c?(c= | ||
g,a()):null===h&&(h=d(function(){h=null;a();c=Date.now()},16-(g-c)))}}w.normalize=function(a){return a instanceof Array?w("[",void 0,void 0,w.normalizeChildren(a),void 0,void 0):null!=a&&"object"!==typeof a?w("#",void 0,void 0,a,void 0,void 0):a};w.normalizeChildren=function(a){for(var c=0;c<a.length;c++)a[c]=w.normalize(a[c]);return a};var P=/(?:(^|#|\.)([^#\.\[\]]+))|(\[(.+?)(?:\s*=\s*("|'|)((?:\\["'\]]|.)*?)\5)?\])/g,K={};z.trust=function(a){null==a&&(a="");return w("<",void 0,void 0,a,void 0, | ||
void 0)};z.fragment=function(a,c){return w("[",a.key,a,w.normalizeChildren(c),void 0,void 0)};var v=function(a){function c(a,b){return function C(c){var l;try{if(!b||null==c||"object"!==typeof c&&"function"!==typeof c||"function"!==typeof(l=c.then))k(function(){b||0!==a.length||console.error("Possible unhandled promise rejection:",c);for(var d=0;d<a.length;d++)a[d](c);g.length=0;m.length=0;p.state=b;p.retry=function(){C(c)}});else{if(c===d)throw new TypeError("Promise can't be resolved w/ itself"); | ||
h(l.bind(c))}}catch(G){n(G)}}}function h(a){function b(b){return function(a){0<c++||b(a)}}var c=0,d=b(n);try{a(b(l),d)}catch(t){d(t)}}if(!(this instanceof v))throw Error("Promise must be called with `new`");if("function"!==typeof a)throw new TypeError("executor must be a function");var d=this,g=[],m=[],l=c(g,!0),n=c(m,!1),p=d._instance={resolvers:g,rejectors:m},k="function"===typeof setImmediate?setImmediate:setTimeout;h(a)};v.prototype.then=function(a,c){function h(a,c,h,l){c.push(function(b){if("function"!== | ||
typeof a)h(b);else try{g(a(b))}catch(D){m&&m(D)}});"function"===typeof d.retry&&l===d.state&&d.retry()}var d=this._instance,g,m,l=new v(function(a,c){g=a;m=c});h(a,d.resolvers,g,!0);h(c,d.rejectors,m,!1);return l};v.prototype["catch"]=function(a){return this.then(null,a)};v.resolve=function(a){return a instanceof v?a:new v(function(c){c(a)})};v.reject=function(a){return new v(function(c,h){h(a)})};v.all=function(a){return new v(function(c,h){var d=a.length,g=0,m=[];if(0===a.length)c([]);else for(var l= | ||
0;l<a.length;l++)(function(l){function p(a){g++;m[l]=a;g===d&&c(m)}null==a[l]||"object"!==typeof a[l]&&"function"!==typeof a[l]||"function"!==typeof a[l].then?p(a[l]):a[l].then(p,h)})(l)})};v.race=function(a){return new v(function(c,h){for(var d=0;d<a.length;d++)a[d].then(c,h)})};"undefined"===typeof E&&("undefined"!==typeof window?window.Promise=v:"undefined"!==typeof global&&(global.Promise=v));var H="undefined"!==typeof E?E:v,I=function(a){function c(a,d){if(d instanceof Array)for(var g=0;g<d.length;g++)c(a+ | ||
"["+g+"]",d[g]);else if("[object Object]"===Object.prototype.toString.call(d))for(g in d)c(a+"["+g+"]",d[g]);else h.push(encodeURIComponent(a)+(null!=d&&""!==d?"="+encodeURIComponent(d):""))}if("[object Object]"!==Object.prototype.toString.call(a))return"";var h=[],d;for(d in a)c(d,a[d]);return h.join("&")},M=function(a,c){function h(){function b(){0===--a&&"function"===typeof r&&r()}var a=0;return function t(c){var d=c.then;c.then=function(){a++;var g=d.apply(c,arguments);g.then(b,function(c){b(); | ||
if(0===a)throw c;});return t(g)};return c}}function d(b,a){if("string"===typeof b){var c=b;b=a||{};null==b.url&&(b.url=c)}return b}function g(b,a){if(null==a)return b;for(var c=b.match(/:[^\/]+/gi)||[],d=0;d<c.length;d++){var g=c[d].slice(1);null!=a[g]&&(b=b.replace(c[d],a[g]),delete a[g])}return b}function m(a,c){var b=I(c);if(""!==b){var d=0>a.indexOf("?")?"?":"&";a+=d+b}return a}function l(a){try{return""!==a?JSON.parse(a):null}catch(D){throw Error(a);}}function n(a){return a.responseText}function p(a, | ||
c){if("function"===typeof a)if(c instanceof Array)for(var b=0;b<c.length;b++)c[b]=new a(c[b]);else return new a(c);return c}var k=0,r;return{request:function(b,k){var r=h();b=d(b,k);var t=new c(function(c,d){null==b.method&&(b.method="GET");b.method=b.method.toUpperCase();var h="boolean"===typeof b.useBody?b.useBody:"GET"!==b.method&&"TRACE"!==b.method;"function"!==typeof b.serialize&&(b.serialize="undefined"!==typeof FormData&&b.data instanceof FormData?function(a){return a}:JSON.stringify);"function"!== | ||
typeof b.deserialize&&(b.deserialize=l);"function"!==typeof b.extract&&(b.extract=n);b.url=g(b.url,b.data);h?b.data=b.serialize(b.data):b.url=m(b.url,b.data);var k=new a.XMLHttpRequest;k.open(b.method,b.url,"boolean"===typeof b.async?b.async:!0,"string"===typeof b.user?b.user:void 0,"string"===typeof b.password?b.password:void 0);b.serialize===JSON.stringify&&h&&k.setRequestHeader("Content-Type","application/json; charset=utf-8");b.deserialize===l&&k.setRequestHeader("Accept","application/json, text/*"); | ||
b.withCredentials&&(k.withCredentials=b.withCredentials);"function"===typeof b.config&&(k=b.config(k,b)||k);k.onreadystatechange=function(){if(4===k.readyState)try{var a=b.extract!==n?b.extract(k,b):b.deserialize(b.extract(k,b));if(200<=k.status&&300>k.status||304===k.status)c(p(b.type,a));else{var g=Error(k.responseText),h;for(h in a)g[h]=a[h];d(g)}}catch(F){d(F)}};h&&null!=b.data?k.send(b.data):k.send()});return!0===b.background?t:r(t)},jsonp:function(b,l){var n=h();b=d(b,l);var t=new c(function(c, | ||
d){var h=b.callbackName||"_mithril_"+Math.round(1E16*Math.random())+"_"+k++,l=a.document.createElement("script");a[h]=function(d){l.parentNode.removeChild(l);c(p(b.type,d));delete a[h]};l.onerror=function(){l.parentNode.removeChild(l);d(Error("JSONP request failed"));delete a[h]};null==b.data&&(b.data={});b.url=g(b.url,b.data);b.data[b.callbackKey||"callback"]=h;l.src=m(b.url,b.data);a.document.documentElement.appendChild(l)});return!0===b.background?t:n(t)},setCompletionCallback:function(a){r=a}}}(window, | ||
H),O=function(a){function c(e,f,a,b,c,d,g){for(;a<b;a++){var q=f[a];null!=q&&p(e,h(q,c,g),d)}}function h(e,f,a){var q=e.tag;null!=e.attrs&&L(e.attrs,e,f);if("string"===typeof q)switch(q){case "#":return e.dom=B.createTextNode(e.children);case "<":return d(e);case "[":var b=B.createDocumentFragment();null!=e.children&&(q=e.children,c(b,q,0,q.length,f,null,a));e.dom=b.firstChild;e.domSize=b.childNodes.length;return b;default:var g=e.tag;switch(e.tag){case "svg":a="http://www.w3.org/2000/svg";break; | ||
case "math":a="http://www.w3.org/1998/Math/MathML"}var p=(q=e.attrs)&&q.is,g=a?p?B.createElementNS(a,g,{is:p}):B.createElementNS(a,g):p?B.createElement(g,{is:p}):B.createElement(g);e.dom=g;if(null!=q)for(b in p=a,q)t(e,b,null,q[b],p);null!=e.attrs&&null!=e.attrs.contenteditable?k(e):(null!=e.text&&(""!==e.text?g.textContent=e.text:e.children=[w("#",void 0,void 0,e.text,void 0,void 0)]),null!=e.children&&(b=e.children,c(g,b,0,b.length,f,null,a),f=e.attrs,"select"===e.tag&&null!=f&&("value"in f&&t(e, | ||
"value",null,f.value,void 0),"selectedIndex"in f&&t(e,"selectedIndex",null,f.selectedIndex,void 0))));return g}else{e.state||(e.state={});R(e.state,e.tag);b=e.tag.view;if(null!=b.reentrantLock)e=E;else if(b.reentrantLock=!0,L(e.tag,e,f),e.instance=w.normalize(b.call(e.state,e)),b.reentrantLock=null,null!=e.instance){if(e.instance===e)throw Error("A view cannot return the vnode it received as arguments");f=h(e.instance,f,a);e.dom=e.instance.dom;e.domSize=null!=e.dom?e.instance.domSize:0;e=f}else e.domSize= | ||
0,e=E;return e}}function d(e){var f={caption:"table",thead:"table",tbody:"table",tfoot:"table",tr:"tbody",th:"tr",td:"tr",colgroup:"table",col:"colgroup"}[(e.children.match(/^\s*?<(\w+)/im)||[])[1]]||"div",f=B.createElement(f);f.innerHTML=e.children;e.dom=f.firstChild;e.domSize=f.childNodes.length;e=B.createDocumentFragment();for(var a;a=f.firstChild;)e.appendChild(a);return e}function g(e,f,a,b,d,g){if(f!==a&&(null!=f||null!=a))if(null==f)c(e,a,0,a.length,b,d,void 0);else if(null==a)r(f,0,f.length, | ||
a);else{for(var q=!1,k=0;k<a.length;k++)if(null!=a[k]){q=null==a[k].key;break}if(f.length===a.length&&q)for(k=0;k<f.length;k++)f[k]!==a[k]&&(null==f[k]?p(e,h(a[k],b,g),n(f,k+1,d)):null==a[k]?r(f,k,k+1,a):m(e,f[k],a[k],b,n(f,k+1,d),!1,g));else{a:{if(null!=f.pool&&Math.abs(f.pool.length-a.length)<=Math.abs(f.length-a.length)&&(q=a[0]&&a[0].children&&a[0].children.length||0,Math.abs((f.pool[0]&&f.pool[0].children&&f.pool[0].children.length||0)-q)<=Math.abs((f[0]&&f[0].children&&f[0].children.length|| | ||
0)-q))){q=!0;break a}q=!1}q&&(f=f.concat(f.pool));for(var A=k=0,y=f.length-1,t=a.length-1,D;y>=k&&t>=A;){var x=f[k],u=a[A];if(x!==u||q)if(null==x)k++;else if(null==u)A++;else if(x.key===u.key)k++,A++,m(e,x,u,b,n(f,k,d),q,g),q&&x.tag===u.tag&&p(e,l(x),d);else if(x=f[y],x!==u||q)if(null==x)y--;else if(null==u)A++;else if(x.key===u.key)m(e,x,u,b,n(f,y+1,d),q,g),(q||A<t)&&p(e,l(x),n(f,k,d)),y--,A++;else break;else y--,A++;else k++,A++}for(;y>=k&&t>=A;){x=f[y];u=a[t];if(x!==u||q)if(null==x)y--;else{if(null!= | ||
u)if(x.key===u.key)m(e,x,u,b,n(f,y+1,d),q,g),q&&x.tag===u.tag&&p(e,l(x),d),null!=x.dom&&(d=x.dom),y--;else{if(!D){D=f;var x=y,C={},w;for(w=0;w<x;w++){var v=D[w];null!=v&&(v=v.key,null!=v&&(C[v]=w))}D=C}null!=u&&(x=D[u.key],null!=x?(C=f[x],m(e,C,u,b,n(f,y+1,d),q,g),p(e,l(C),d),f[x].skip=!0,null!=C.dom&&(d=C.dom)):(u=h(u,b,void 0),p(e,u,d),d=u))}t--}else y--,t--;if(t<A)break}c(e,a,A,t+1,b,d,g);r(f,k,y+1,a)}}}function m(a,f,b,c,u,y,n){var e=f.tag;if(e===b.tag){b.state=f.state;b.events=f.events;var q; | ||
var A;null!=b.attrs&&"function"===typeof b.attrs.onbeforeupdate&&(q=b.attrs.onbeforeupdate.call(b.state,b,f));"string"!==typeof b.tag&&"function"===typeof b.tag.onbeforeupdate&&(A=b.tag.onbeforeupdate.call(b.state,b,f));void 0===q&&void 0===A||q||A?q=!1:(b.dom=f.dom,b.domSize=f.domSize,b.instance=f.instance,q=!0);if(!q)if(null!=b.attrs&&z(b.attrs,b,c,y),"string"===typeof e)switch(e){case "#":f.children.toString()!==b.children.toString()&&(f.dom.nodeValue=b.children);b.dom=f.dom;break;case "<":f.children!== | ||
b.children?(l(f),p(a,d(b),u)):(b.dom=f.dom,b.domSize=f.domSize);break;case "[":g(a,f.children,b.children,c,u,n);f=0;c=b.children;b.dom=null;if(null!=c){for(var r=0;r<c.length;r++)a=c[r],null!=a&&null!=a.dom&&(null==b.dom&&(b.dom=a.dom),f+=a.domSize||1);1!==f&&(b.domSize=f)}break;default:a=n;u=b.dom=f.dom;switch(b.tag){case "svg":a="http://www.w3.org/2000/svg";break;case "math":a="http://www.w3.org/1998/Math/MathML"}"textarea"===b.tag&&(null==b.attrs&&(b.attrs={}),null!=b.text&&(b.attrs.value=b.text, | ||
b.text=void 0));y=f.attrs;n=b.attrs;e=a;if(null!=n)for(r in n)t(b,r,y&&y[r],n[r],e);if(null!=y)for(r in y)null!=n&&r in n||("className"===r&&(r="class"),"o"!==r[0]||"n"!==r[1]||v(r)?"key"!==r&&b.dom.removeAttribute(r):G(b,r,void 0));null!=b.attrs&&null!=b.attrs.contenteditable?k(b):null!=f.text&&null!=b.text&&""!==b.text?f.text.toString()!==b.text.toString()&&(f.dom.firstChild.nodeValue=b.text):(null!=f.text&&(f.children=[w("#",void 0,void 0,f.text,void 0,f.dom.firstChild)]),null!=b.text&&(b.children= | ||
[w("#",void 0,void 0,b.text,void 0,void 0)]),g(u,f.children,b.children,c,null,a))}else b.instance=w.normalize(b.tag.view.call(b.state,b)),z(b.tag,b,c,y),null!=b.instance?(null==f.instance?p(a,h(b.instance,c,n),u):m(a,f.instance,b.instance,c,u,y,n),b.dom=b.instance.dom,b.domSize=b.instance.domSize):null!=f.instance?(D(f.instance,null),b.dom=void 0,b.domSize=0):(b.dom=f.dom,b.domSize=f.domSize)}else D(f,null),p(a,h(b,c,n),u)}function l(b){var a=b.domSize;if(null!=a||null==b.dom){var e=B.createDocumentFragment(); | ||
if(0<a){for(b=b.dom;--a;)e.appendChild(b.nextSibling);e.insertBefore(b,e.firstChild)}return e}return b.dom}function n(b,a,c){for(;a<b.length;a++)if(null!=b[a]&&null!=b[a].dom)return b[a].dom;return c}function p(b,a,c){c&&c.parentNode?b.insertBefore(a,c):b.appendChild(a)}function k(b){var a=b.children;if(null!=a&&1===a.length&&"<"===a[0].tag)a=a[0].children,b.dom.innerHTML!==a&&(b.dom.innerHTML=a);else if(null!=b.text||null!=a&&0!==a.length)throw Error("Child node of a contenteditable must be trusted"); | ||
}function r(b,a,c,d){for(;a<c;a++){var e=b[a];null!=e&&(e.skip?e.skip=!1:D(e,d))}}function b(b){var a=!1;return function(){a||(a=!0,b())}}function D(a,f){function e(){if(++d===c&&(C(a),a.dom)){var b=a.domSize||1;if(1<b)for(var e=a.dom;--b;){var g=e.nextSibling,k=g.parentNode;null!=k&&k.removeChild(g)}b=a.dom;e=b.parentNode;null!=e&&e.removeChild(b);if(b=null!=f&&null==a.domSize)b=a.attrs,b=!(null!=b&&(b.oncreate||b.onupdate||b.onbeforeremove||b.onremove));b&&"string"===typeof a.tag&&(f.pool?f.pool.push(a): | ||
f.pool=[a])}}var c=1,d=0;a.attrs&&a.attrs.onbeforeremove&&(c++,a.attrs.onbeforeremove.call(a.state,a,b(e)));"string"!==typeof a.tag&&a.tag.onbeforeremove&&(c++,a.tag.onbeforeremove.call(a.state,a,b(e)));e()}function C(b){b.attrs&&b.attrs.onremove&&b.attrs.onremove.call(b.state,b);"string"!==typeof b.tag&&b.tag.onremove&&b.tag.onremove.call(b.state,b);if(null!=b.instance)C(b.instance);else if(b=b.children,b instanceof Array)for(var a=0;a<b.length;a++){var e=b[a];null!=e&&C(e)}}function t(b,a,c,d,g){var e= | ||
b.dom;if("key"!==a&&(c!==d||"value"===a||"checked"===a||"selectedIndex"===a||"selected"===a&&b.dom===B.activeElement||"object"===typeof d)&&"undefined"!==typeof d&&!v(a)){var f=a.indexOf(":");if(-1<f&&"xlink"===a.substr(0,f))e.setAttributeNS("http://www.w3.org/1999/xlink",a.slice(f+1),d);else if("o"===a[0]&&"n"===a[1]&&"function"===typeof d)G(b,a,d);else if("style"===a)if(b=c,b===d&&(e.style.cssText="",b=null),null==d)e.style.cssText="";else if("string"===typeof d)e.style.cssText=d;else{"string"=== | ||
typeof b&&(e.style.cssText="");for(var k in d)e.style[k]=d[k];if(null!=b&&"string"!==typeof b)for(k in b)k in d||(e.style[k]="")}else a in e&&"href"!==a&&"list"!==a&&"form"!==a&&"width"!==a&&"height"!==a&&void 0===g?"input"===b.tag&&"value"===a&&b.dom.value===d&&b.dom===B.activeElement||"select"===b.tag&&"value"===a&&b.dom.value===d&&b.dom===B.activeElement||"option"===b.tag&&"value"===a&&b.dom.value===d||(e[a]=d):"boolean"===typeof d?d?e.setAttribute(a,""):e.removeAttribute(a):e.setAttribute("className"=== | ||
a?"class":a,d)}}function v(b){return"oninit"===b||"oncreate"===b||"onupdate"===b||"onremove"===b||"onbeforeremove"===b||"onbeforeupdate"===b}function G(b,a,c){var d=b.dom,e="function"!==typeof F?c:function(b){var a=c.call(d,b);F.call(d,b);return a};if(a in d)d[a]="function"===typeof c?e:null;else{var f=a.slice(2);void 0===b.events&&(b.events={});b.events[a]!==e&&(null!=b.events[a]&&d.removeEventListener(f,b.events[a],!1),"function"===typeof c&&(b.events[a]=e,d.addEventListener(f,b.events[a],!1)))}} | ||
function L(b,a,c){"function"===typeof b.oninit&&b.oninit.call(a.state,a);"function"===typeof b.oncreate&&c.push(b.oncreate.bind(a.state,a))}function z(b,a,c,d){d?L(b,a,c):"function"===typeof b.onupdate&&c.push(b.onupdate.bind(a.state,a))}function R(b,a){Object.keys(a).forEach(function(c){b[c]=a[c]})}var B=a.document,E=B.createDocumentFragment(),F;return{render:function(b,a){if(!b)throw Error("Ensure the DOM element being passed to m.route/m.mount/m.render is not undefined.");var c=[],d=B.activeElement; | ||
null==b.vnodes&&(b.textContent="");a instanceof Array||(a=[a]);g(b,b.vnodes,w.normalizeChildren(a),c,null,void 0);b.vnodes=a;for(var e=0;e<c.length;e++)c[e]();B.activeElement!==d&&d.focus()},setEventCallback:function(b){return F=b}}},J=function(a){function c(a){a=d.indexOf(a);-1<a&&d.splice(a,2)}function h(){for(var a=1;a<d.length;a+=2)d[a]()}a=O(a);a.setEventCallback(function(a){!1!==a.redraw&&h()});var d=[];return{subscribe:function(a,h){c(a);d.push(a,Q(h))},unsubscribe:c,redraw:h,render:a.render}}(window); | ||
M.setCompletionCallback(J.redraw);z.mount=function(a){return function(c,h){if(null===h)a.render(c,[]),a.unsubscribe(c);else{if(null==h.view)throw Error("m.mount(element, component) expects a component, not a vnode");a.subscribe(c,function(){a.render(c,w(h))});a.redraw()}}}(J);var E=H,N=function(a){if(""===a||null==a)return{};"?"===a.charAt(0)&&(a=a.slice(1));a=a.split("&");for(var c={},h={},d=0;d<a.length;d++){var g=a[d].split("="),m=decodeURIComponent(g[0]),g=2===g.length?decodeURIComponent(g[1]): | ||
"";"true"===g?g=!0:"false"===g&&(g=!1);var l=m.split(/\]\[?|\[/),n=c;-1<m.indexOf("[")&&l.pop();for(var p=0;p<l.length;p++){var m=l[p],k=l[p+1],k=""==k||!isNaN(parseInt(k,10)),r=p===l.length-1;""===m&&(m=l.slice(0,p).join(),null==h[m]&&(h[m]=0),m=h[m]++);null==n[m]&&(n[m]=r?g:k?[]:{});n=n[m]}}return c},S=function(a){function c(c){var d=a.location[c].replace(/(?:%[a-f89][a-f0-9])+/gim,decodeURIComponent);"pathname"===c&&"/"!==d[0]&&(d="/"+d);return d}function h(a){return function(){null==l&&(l=m(function(){l= | ||
null;a()}))}}function d(a,c,d){var b=a.indexOf("?"),g=a.indexOf("#"),k=-1<b?b:-1<g?g:a.length;if(-1<b){var b=N(a.slice(b+1,-1<g?g:a.length)),h;for(h in b)c[h]=b[h]}if(-1<g)for(h in c=N(a.slice(g+1)),c)d[h]=c[h];return a.slice(0,k)}var g="function"===typeof a.history.pushState,m="function"===typeof setImmediate?setImmediate:setTimeout,l,n={prefix:"#!",getPath:function(){switch(n.prefix.charAt(0)){case "#":return c("hash").slice(n.prefix.length);case "?":return c("search").slice(n.prefix.length)+c("hash"); | ||
default:return c("pathname").slice(n.prefix.length)+c("search")+c("hash")}},setPath:function(c,k,h){var b={},l={};c=d(c,b,l);if(null!=k){for(var m in k)b[m]=k[m];c=c.replace(/:([^\/]+)/g,function(a,c){delete b[c];return k[c]})}(m=I(b))&&(c+="?"+m);(l=I(l))&&(c+="#"+l);g?(h&&h.replace?a.history.replaceState(null,null,n.prefix+c):a.history.pushState(null,null,n.prefix+c),a.onpopstate()):a.location.href=n.prefix+c},defineRoutes:function(c,k,l){function b(){var a=n.getPath(),b={},g=d(a,b,b),h;for(h in c){var m= | ||
new RegExp("^"+h.replace(/:[^\/]+?\.{3}/g,"(.*?)").replace(/:[^\/]+/g,"([^\\/]+)")+"/?$");if(m.test(g)){g.replace(m,function(){for(var d=h.match(/:[^\/]+/g)||[],g=[].slice.call(arguments,1,-2),l=0;l<d.length;l++)b[d[l].replace(/:|\./g,"")]=decodeURIComponent(g[l]);k(c[h],b,a,h)});return}}l(a,b)}g?a.onpopstate=h(b):"#"===n.prefix.charAt(0)&&(a.onhashchange=b);b()}};return n};z.route=function(a,c){var h=S(a),d=function(a){return a},g,m,l,n,p=!1,k=function(a,b,k){if(null==a)throw Error("Ensure the DOM element that was passed to `m.route` is not undefined"); | ||
var r=function(a,b,c,h){m=null!=b&&"function"===typeof b.view?b:"div";l=c;n=h;p=!1;g=(a.render||d).bind(a);t()},t=function(){null!=g&&c.render(a,g(w(m,l.key,l)))},v=function(){h.setPath(b)};h.defineRoutes(k,function(a,b,c){a.view?r({},a,b,c):a.onmatch?(p=!0,E.resolve(a.onmatch(b,c)).then(function(d){p&&r(a,d,b,c)},v)):r(a,"div",b,c)},v);c.subscribe(a,t)};k.set=function(a,b,c){p&&(c={replace:!0});p=!1;h.setPath(a,b,c)};k.get=function(){return n};k.prefix=function(a){h.prefix=a};k.link=function(a){a.dom.setAttribute("href", | ||
h.prefix+a.attrs.href);a.dom.onclick=function(a){a.ctrlKey||a.metaKey||a.shiftKey||2===a.which||(a.preventDefault(),a.redraw=!1,a=this.getAttribute("href"),0===a.indexOf(h.prefix)&&(a=a.slice(h.prefix.length)),k.set(a,void 0,void 0))}};return k}(window,J);z.withAttr=function(a,c,h){return function(d){return c.call(h||this,a in d.currentTarget?d.currentTarget[a]:d.currentTarget.getAttribute(a))}};H=O(window);z.render=H.render;z.redraw=J.redraw;z.request=M.request;z.jsonp=M.jsonp;z.parseQueryString= | ||
N;z.buildQueryString=I;z.version="1.0.0-rc.6";"undefined"!==typeof module?module.exports=z:window.m=z}; |
@@ -1,4 +0,3 @@ | ||
var renderService = require("./render") | ||
var redrawService = require("./redraw") | ||
module.exports = require("./api/mount")(renderService, redrawService) | ||
module.exports = require("./api/mount")(redrawService) |
@@ -205,3 +205,6 @@ "use strict" | ||
} | ||
console.log(results.length + " assertions completed in " + Math.round(new Date - start) + "ms") | ||
console.log( | ||
results.length + " assertions completed in " + Math.round(new Date - start) + "ms, " + | ||
"of which " + results.filter(function(result){return result.error}).length + " failed" | ||
) | ||
if (hasProcess && status === 1) process.exit(1) | ||
@@ -208,0 +211,0 @@ } |
{ | ||
"name": "ospec", | ||
"version": "1.2.0", | ||
"version": "1.2.1", | ||
"description": "Noiseless testing framework", | ||
@@ -5,0 +5,0 @@ "main": "ospec.js", |
@@ -7,3 +7,3 @@ # ospec | ||
Version: 1.2 | ||
Version: 1.2.1 | ||
License: MIT | ||
@@ -10,0 +10,0 @@ |
{ | ||
"name": "mithril", | ||
"version": "1.0.0-rc.5", | ||
"version": "1.0.0-rc.6", | ||
"description": "A framework for building brilliant applications", | ||
@@ -15,2 +15,3 @@ "author": "Leo Horie", | ||
"lintdocs": "node docs/lint", | ||
"gendocs": "node docs/generate", | ||
"lint": "eslint .", | ||
@@ -22,3 +23,4 @@ "test": "node ospec/bin/ospec", | ||
"eslint": "^2.10.2", | ||
"istanbul": "^0.4.3" | ||
"istanbul": "^0.4.3", | ||
"marked": "^0.3.6" | ||
}, | ||
@@ -25,0 +27,0 @@ "publishConfig": { |
@@ -406,2 +406,23 @@ "use strict" | ||
}) | ||
o("triggers all branched rejection handlers upon rejection", function(done) { | ||
var promise = Promise.reject() | ||
var then = o.spy() | ||
var catch1 = o.spy() | ||
var catch2 = o.spy() | ||
var catch3 = o.spy() | ||
promise.catch(catch1) | ||
promise.then(then, catch2) | ||
promise.then(then).catch(catch3) | ||
callAsync(function() { | ||
callAsync(function() { | ||
o(catch1.callCount).equals(1) | ||
o(then.callCount).equals(0) | ||
o(catch2.callCount).equals(1) | ||
o(catch3.callCount).equals(1) | ||
done() | ||
}) | ||
}) | ||
}) | ||
o("does not absorb resolved promise via static rejector", function(done) { | ||
@@ -408,0 +429,0 @@ var promise = Promise.reject(Promise.resolve(1)) |
# Mithril.js - A framework for building brilliant applications | ||
[Installation](docs/installation.md) | [API](docs/api.md) | [Examples](docs/examples.md) | [Migration Guide](docs/v1.x-migration.md) | ||
[Installation](docs/installation.md) | [API](docs/api.md) | [Examples](docs/examples.md) | [Changelog/Migration Guide](docs/change-log.md) | ||
Note: This branch is the upcoming version 1.0. It's a rewrite from the ground up and it's not backwards compatible with [Mithril 0.2.x](http://mithril.js.org). You can find preliminary [documentation here](docs) and [migration guide here](docs/v1.x-migration.md) | ||
Note: This branch is the upcoming version 1.0. It's a rewrite from the ground up and it's not backwards compatible with [Mithril 0.2.x](http://mithril.js.org). You can find preliminary [documentation here](docs) and [migration guide here](docs/change-log.md) | ||
@@ -37,4 +37,4 @@ This rewrite aims to fix longstanding API design issues, significantly improve performance, and clean up the codebase. | ||
Despite the huge improvements in performance and modularity, the new codebase is smaller than v0.2.x, currently clocking at <!-- size -->7.37 KB<!-- /size --> min+gzip | ||
Despite the huge improvements in performance and modularity, the new codebase is smaller than v0.2.x, currently clocking at <!-- size -->7.47 KB<!-- /size --> min+gzip | ||
In addition, Mithril is now completely modular: you can import only the modules that you need and easily integrate 3rd party modules if you wish to use a different library for routing, ajax, and even rendering |
@@ -1,1 +0,1 @@ | ||
module.exports = require("./api/pubsub")() | ||
module.exports = require("./api/redraw")(window) |
@@ -22,3 +22,4 @@ "use strict" | ||
if (attrValue) attrValue = attrValue.replace(/\\(["'])/g, "$1").replace(/\\\\/g, "\\") | ||
attributes[match[4]] = attrValue || true | ||
if (match[4] === "class") classes.push(attrValue) | ||
else attributes[match[4]] = attrValue || true | ||
} | ||
@@ -25,0 +26,0 @@ } |
@@ -127,15 +127,21 @@ "use strict" | ||
else { | ||
var recycling = isRecyclable(old, vnodes) | ||
if (recycling) old = old.concat(old.pool) | ||
if (old.length === vnodes.length && vnodes[0] != null && vnodes[0].key == null) { | ||
var isUnkeyed = false | ||
for (var i = 0; i < vnodes.length; i++) { | ||
if (vnodes[i] != null) { | ||
isUnkeyed = vnodes[i].key == null | ||
break | ||
} | ||
} | ||
if (old.length === vnodes.length && isUnkeyed) { | ||
for (var i = 0; i < old.length; i++) { | ||
if (old[i] === vnodes[i] || old[i] == null && vnodes[i] == null) continue | ||
if (old[i] === vnodes[i]) continue | ||
else if (old[i] == null) insertNode(parent, createNode(vnodes[i], hooks, ns), getNextSibling(old, i + 1, nextSibling)) | ||
else if (vnodes[i] == null) removeNodes(old, i, i + 1, vnodes) | ||
else updateNode(parent, old[i], vnodes[i], hooks, getNextSibling(old, i + 1, nextSibling), recycling, ns) | ||
if (recycling && old[i].tag === vnodes[i].tag) insertNode(parent, toFragment(old[i]), getNextSibling(old, i + 1, nextSibling)) | ||
else updateNode(parent, old[i], vnodes[i], hooks, getNextSibling(old, i + 1, nextSibling), false, ns) | ||
} | ||
} | ||
else { | ||
var recycling = isRecyclable(old, vnodes) | ||
if (recycling) old = old.concat(old.pool) | ||
var oldStart = 0, start = 0, oldEnd = old.length - 1, end = vnodes.length - 1, map | ||
@@ -145,3 +151,5 @@ while (oldEnd >= oldStart && end >= start) { | ||
if (o === v && !recycling) oldStart++, start++ | ||
else if (o != null && v != null && o.key === v.key) { | ||
else if (o == null) oldStart++ | ||
else if (v == null) start++ | ||
else if (o.key === v.key) { | ||
oldStart++, start++ | ||
@@ -154,3 +162,5 @@ updateNode(parent, o, v, hooks, getNextSibling(old, oldStart, nextSibling), recycling, ns) | ||
if (o === v && !recycling) oldEnd--, start++ | ||
else if (o != null && v != null && o.key === v.key) { | ||
else if (o == null) oldEnd-- | ||
else if (v == null) start++ | ||
else if (o.key === v.key) { | ||
updateNode(parent, o, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), recycling, ns) | ||
@@ -166,3 +176,5 @@ if (recycling || start < end) insertNode(parent, toFragment(o), getNextSibling(old, oldStart, nextSibling)) | ||
if (o === v && !recycling) oldEnd--, end-- | ||
else if (o != null && v != null && o.key === v.key) { | ||
else if (o == null) oldEnd-- | ||
else if (v == null) end-- | ||
else if (o.key === v.key) { | ||
updateNode(parent, o, v, hooks, getNextSibling(old, oldEnd + 1, nextSibling), recycling, ns) | ||
@@ -349,3 +361,3 @@ if (recycling && o.tag === v.tag) insertNode(parent, toFragment(o), nextSibling) | ||
} | ||
else if (children != null || vnode.text != null) throw new Error("Child node of a contenteditable must be trusted") | ||
else if (vnode.text != null || children != null && children.length !== 0) throw new Error("Child node of a contenteditable must be trusted") | ||
} | ||
@@ -440,2 +452,6 @@ | ||
if (vnode.tag === "input" && key === "value" && vnode.dom.value === value && vnode.dom === $doc.activeElement) return | ||
//setting select[value] to same value while having select open blinks select dropdown in Chrome | ||
if (vnode.tag === "select" && key === "value" && vnode.dom.value === value && vnode.dom === $doc.activeElement) return | ||
//setting option[value] to same value while having select open blinks select dropdown in Chrome | ||
if (vnode.tag === "option" && key === "value" && vnode.dom.value === value) return | ||
element[key] = value | ||
@@ -508,5 +524,5 @@ } | ||
var element = vnode.dom | ||
var callback = function(e) { | ||
var callback = typeof onevent !== "function" ? value : function(e) { | ||
var result = value.call(element, e) | ||
if (typeof onevent === "function") onevent.call(element, e) | ||
onevent.call(element, e) | ||
return result | ||
@@ -518,2 +534,3 @@ } | ||
if (vnode.events === undefined) vnode.events = {} | ||
if (vnode.events[key] === callback) return | ||
if (vnode.events[key] != null) element.removeEventListener(eventName, vnode.events[key], false) | ||
@@ -520,0 +537,0 @@ if (typeof value === "function") { |
@@ -82,5 +82,5 @@ "use strict" | ||
var canvas = {tag: "canvas", attrs: {width: "100%"}} | ||
render(root, canvas) | ||
o(canvas.dom.attributes["width"].nodeValue).equals("100%") | ||
@@ -99,2 +99,56 @@ o(canvas.dom.width).equals(100) | ||
}) | ||
o.spec("contenteditable throws on untrusted children", function() { | ||
o("including text nodes", function() { | ||
var div = {tag: "div", attrs: {contenteditable: true}, text: ''} | ||
var succeeded = false | ||
try { | ||
render(root, div) | ||
succeeded = true | ||
} | ||
catch(e){} | ||
o(succeeded).equals(false) | ||
}) | ||
o("including elements", function() { | ||
var div = {tag: "div", attrs: {contenteditable: true}, children: [{tag: "script", attrs: {src: "http://evil.com"}}]} | ||
var succeeded = false | ||
try { | ||
render(root, div) | ||
succeeded = true | ||
} | ||
catch(e){} | ||
o(succeeded).equals(false) | ||
}) | ||
o("tolerating empty children", function() { | ||
var div = {tag: "div", attrs: {contenteditable: true}, children: []} | ||
var succeeded = false | ||
try { | ||
render(root, div) | ||
succeeded = true | ||
} | ||
catch(e){} | ||
o(succeeded).equals(true) | ||
}) | ||
o("tolerating trusted content", function() { | ||
var div = {tag: "div", attrs: {contenteditable: true}, children: [{tag: "<", children: "<a></a>"}]} | ||
var succeeded = false | ||
try { | ||
render(root, div) | ||
succeeded = true | ||
} | ||
catch(e){} | ||
o(succeeded).equals(true) | ||
}) | ||
}) | ||
}) |
@@ -187,2 +187,7 @@ var o = require("../../ospec/ospec") | ||
}) | ||
o("handles 'class' as a verbose attribute declaration", function() { | ||
var vnode = m("[class=a]") | ||
o(vnode.attrs.className).equals("a") | ||
}) | ||
o("handles merging classes w/ class property", function() { | ||
@@ -189,0 +194,0 @@ var vnode = m(".a", {class: "b"}) |
@@ -718,2 +718,18 @@ "use strict" | ||
}) | ||
o("change type, position and length", function() { | ||
var vnodes = {tag: "div", children: [ | ||
undefined, | ||
{tag: "#", children: "a"} | ||
]} | ||
var updated = {tag: "div", children: [ | ||
{tag: "[", children: [{tag: "#", children: "b"}]}, | ||
undefined, | ||
undefined | ||
]} | ||
render(root, vnodes) | ||
render(root, updated) | ||
o(root.firstChild.childNodes.length).equals(1) | ||
}) | ||
o("removes then recreates then reverses children", function() { | ||
@@ -867,2 +883,40 @@ var vnodes = [{tag: "a", key: 1, children: [{tag: "i", key: 3}, {tag: "s", key: 4}]}, {tag: "b", key: 2}] | ||
}) | ||
o("null stays in place", function() { | ||
var create = o.spy() | ||
var update = o.spy() | ||
var remove = o.spy() | ||
var vnodes = [{tag: "div"}, {tag: "a", attrs: {oncreate: create, onupdate: update, onremove: remove}}] | ||
var temp = [null, {tag: "a", attrs: {oncreate: create, onupdate: update, onremove: remove}}] | ||
var updated = [{tag: "div"}, {tag: "a", attrs: {oncreate: create, onupdate: update, onremove: remove}}] | ||
render(root, vnodes) | ||
var before = vnodes[1].dom | ||
render(root, temp) | ||
render(root, updated) | ||
var after = updated[1].dom | ||
o(before).equals(after) | ||
o(create.callCount).equals(1) | ||
o(update.callCount).equals(2) | ||
o(remove.callCount).equals(0) | ||
}) | ||
o("null stays in place if not first", function() { | ||
var create = o.spy() | ||
var update = o.spy() | ||
var remove = o.spy() | ||
var vnodes = [{tag: "b"}, {tag: "div"}, {tag: "a", attrs: {oncreate: create, onupdate: update, onremove: remove}}] | ||
var temp = [{tag: "b"}, null, {tag: "a", attrs: {oncreate: create, onupdate: update, onremove: remove}}] | ||
var updated = [{tag: "b"}, {tag: "div"}, {tag: "a", attrs: {oncreate: create, onupdate: update, onremove: remove}}] | ||
render(root, vnodes) | ||
var before = vnodes[2].dom | ||
render(root, temp) | ||
render(root, updated) | ||
var after = updated[2].dom | ||
o(before).equals(after) | ||
o(create.callCount).equals(1) | ||
o(update.callCount).equals(2) | ||
o(remove.callCount).equals(0) | ||
}) | ||
}) |
@@ -8,29 +8,36 @@ "use strict" | ||
var count = 0 | ||
var oncompletion | ||
function setCompletionCallback(callback) {oncompletion = callback} | ||
function complete() {if (--count === 0 && typeof oncompletion === "function") oncompletion()} | ||
function finalizer() { | ||
var count = 0 | ||
function complete() {if (--count === 0 && typeof oncompletion === "function") oncompletion()} | ||
function finalize(promise) { | ||
var then = promise.then | ||
promise.then = function() { | ||
count++ | ||
var next = then.apply(promise, arguments) | ||
next.then(complete, function(e) { | ||
complete() | ||
throw e | ||
}) | ||
return finalize(next) | ||
return function finalize(promise) { | ||
var then = promise.then | ||
promise.then = function() { | ||
count++ | ||
var next = then.apply(promise, arguments) | ||
next.then(complete, function(e) { | ||
complete() | ||
if (count === 0) throw e | ||
}) | ||
return finalize(next) | ||
} | ||
return promise | ||
} | ||
return promise | ||
} | ||
function normalize(args, extra) { | ||
if (typeof args === "string") { | ||
var url = args | ||
args = extra || {} | ||
if (args.url == null) args.url = url | ||
} | ||
return args | ||
} | ||
function request(args, extra) { | ||
return finalize(new Promise(function(resolve, reject) { | ||
if (typeof args === "string") { | ||
var url = args | ||
args = extra || {} | ||
if (args.url == null) args.url = url | ||
} | ||
var finalize = finalizer() | ||
args = normalize(args, extra) | ||
var promise = new Promise(function(resolve, reject) { | ||
if (args.method == null) args.method = "GET" | ||
@@ -58,2 +65,3 @@ args.method = args.method.toUpperCase() | ||
} | ||
if (args.withCredentials) xhr.withCredentials = args.withCredentials | ||
@@ -83,7 +91,11 @@ if (typeof args.config === "function") xhr = args.config(xhr, args) || xhr | ||
else xhr.send() | ||
})) | ||
}) | ||
return args.background === true ? promise : finalize(promise) | ||
} | ||
function jsonp(args) { | ||
return finalize(new Promise(function(resolve, reject) { | ||
function jsonp(args, extra) { | ||
var finalize = finalizer() | ||
args = normalize(args, extra) | ||
var promise = new Promise(function(resolve, reject) { | ||
var callbackName = args.callbackName || "_mithril_" + Math.round(Math.random() * 1e16) + "_" + callbackCount++ | ||
@@ -106,3 +118,4 @@ var script = $window.document.createElement("script") | ||
$window.document.documentElement.appendChild(script) | ||
})) | ||
}) | ||
return args.background === true? promise : finalize(promise) | ||
} | ||
@@ -109,0 +122,0 @@ |
@@ -10,6 +10,9 @@ "use strict" | ||
o.spec("jsonp", function() { | ||
var mock, jsonp, spy | ||
var mock, jsonp, spy, complete | ||
o.beforeEach(function() { | ||
mock = xhrMock() | ||
jsonp = new Request(mock, Promise).jsonp | ||
var requestService = Request(mock, Promise) | ||
jsonp = requestService.jsonp | ||
complete = o.spy() | ||
requestService.setCompletionCallback(complete) | ||
}) | ||
@@ -28,2 +31,16 @@ | ||
}) | ||
o("first argument can be a string aliasing url property", function(done){ | ||
var s = new Date | ||
mock.$defineRoutes({ | ||
"GET /item": function(request) { | ||
var queryData = parseQueryString(request.query) | ||
return {status: 200, responseText: queryData["callback"] + "(" + JSON.stringify({a: 1}) + ")"} | ||
} | ||
}) | ||
jsonp("/item").then(function(data) { | ||
o(data).deepEquals({a: 1}) | ||
}).then(function() { | ||
done() | ||
}) | ||
}) | ||
o("works w/ other querystring params", function(done) { | ||
@@ -52,2 +69,60 @@ mock.$defineRoutes({ | ||
}) | ||
o("works w/ custom callbackKey", function(done) { | ||
mock.$defineRoutes({ | ||
"GET /item": function(request) { | ||
var queryData = parseQueryString(request.query) | ||
return {status: 200, responseText: queryData["cb"] + "(" + JSON.stringify({a: 2}) + ")"} | ||
} | ||
}) | ||
jsonp({url: "/item", callbackKey: "cb"}).then(function(data) { | ||
o(data).deepEquals({a: 2}) | ||
}).then(done) | ||
}) | ||
o("requests don't block each other", function(done) { | ||
mock.$defineRoutes({ | ||
"GET /item": function(request) { | ||
var queryData = parseQueryString(request.query) | ||
return {status: 200, responseText: queryData["callback"] + "([])"} | ||
} | ||
}) | ||
jsonp("/item").then(function() { | ||
return jsonp("/item") | ||
}) | ||
jsonp("/item").then(function() { | ||
return jsonp("/item") | ||
}) | ||
setTimeout(function() { | ||
o(complete.callCount).equals(4) | ||
done() | ||
}, 20) | ||
}) | ||
o("requests trigger finally once with a chained then", function(done) { | ||
mock.$defineRoutes({ | ||
"GET /item": function(request) { | ||
var queryData = parseQueryString(request.query) | ||
return {status: 200, responseText: queryData["callback"] + "([])"} | ||
} | ||
}) | ||
var promise = jsonp("/item") | ||
promise.then(function() {}).then(function() {}) | ||
promise.then(function() {}).then(function() {}) | ||
setTimeout(function() { | ||
o(complete.callCount).equals(1) | ||
done() | ||
}, 20) | ||
}) | ||
o("requests does not trigger finally when background: true", function(done) { | ||
mock.$defineRoutes({ | ||
"GET /item": function(request) { | ||
var queryData = parseQueryString(request.query) | ||
return {status: 200, responseText: queryData["callback"] + "([])"} | ||
} | ||
}) | ||
var promise = jsonp("/item", {background: true}).then(function() {}) | ||
setTimeout(function() { | ||
o(complete.callCount).equals(0) | ||
done() | ||
}, 20) | ||
}) | ||
o("handles error", function(done) { | ||
@@ -54,0 +129,0 @@ jsonp({url: "/item", callbackKey: "cb"}).catch(function(e) { |
"use strict" | ||
var o = require("../../ospec/ospec") | ||
var callAsync = require("../../test-utils/callAsync") | ||
var xhrMock = require("../../test-utils/xhrMock") | ||
@@ -9,6 +10,9 @@ var Request = require("../../request/request") | ||
o.spec("xhr", function() { | ||
var mock, xhr | ||
var mock, xhr, complete | ||
o.beforeEach(function() { | ||
mock = xhrMock() | ||
xhr = new Request(mock, Promise).request | ||
var requestService = Request(mock, Promise) | ||
xhr = requestService.request | ||
complete = o.spy() | ||
requestService.setCompletionCallback(complete) | ||
}) | ||
@@ -299,2 +303,46 @@ | ||
}) | ||
o("requests don't block each other", function(done) { | ||
mock.$defineRoutes({ | ||
"GET /item": function(request) { | ||
return {status: 200, responseText: "[]"} | ||
} | ||
}) | ||
xhr("/item").then(function() { | ||
return xhr("/item") | ||
}) | ||
xhr("/item").then(function() { | ||
return xhr("/item") | ||
}) | ||
setTimeout(function() { | ||
o(complete.callCount).equals(4) | ||
done() | ||
}, 20) | ||
}) | ||
o("requests trigger finally once with a chained then", function(done) { | ||
mock.$defineRoutes({ | ||
"GET /item": function(request) { | ||
return {status: 200, responseText: "[]"} | ||
} | ||
}) | ||
var promise = xhr("/item") | ||
promise.then(function() {}).then(function() {}) | ||
promise.then(function() {}).then(function() {}) | ||
setTimeout(function() { | ||
o(complete.callCount).equals(1) | ||
done() | ||
}, 20) | ||
}) | ||
o("requests does not trigger finally when background: true", function(done) { | ||
mock.$defineRoutes({ | ||
"GET /item": function(request) { | ||
return {status: 200, responseText: "[]"} | ||
} | ||
}) | ||
var promise = xhr("/item", {background: true}).then(function() {}) | ||
setTimeout(function() { | ||
o(complete.callCount).equals(0) | ||
done() | ||
}, 20) | ||
}) | ||
}) | ||
@@ -335,3 +383,29 @@ o.spec("failure", function() { | ||
}) | ||
o("triggers all branched catches upon rejection", function(done) { | ||
mock.$defineRoutes({ | ||
"GET /item": function(request) { | ||
return {status: 500, responseText: "error"} | ||
} | ||
}) | ||
var request = xhr({method: "GET", url: "/item"}) | ||
var then = o.spy() | ||
var catch1 = o.spy() | ||
var catch2 = o.spy() | ||
var catch3 = o.spy() | ||
request.catch(catch1) | ||
request.then(then, catch2) | ||
request.then(then).catch(catch3) | ||
callAsync(function() { | ||
callAsync(function() { | ||
o(catch1.callCount).equals(1) | ||
o(then.callCount).equals(0) | ||
o(catch2.callCount).equals(1) | ||
o(catch3.callCount).equals(1) | ||
done() | ||
}) | ||
}) | ||
}) | ||
}) | ||
}) |
@@ -1,3 +0,3 @@ | ||
var mount = require("./mount") | ||
var redrawService = require("./redraw") | ||
module.exports = require("./api/router")(window, mount) | ||
module.exports = require("./api/router")(window, redrawService) |
@@ -10,5 +10,2 @@ "use strict" | ||
var prefix = "#!" | ||
function setPrefix(value) {prefix = value} | ||
function normalize(fragment) { | ||
@@ -21,3 +18,3 @@ var data = $window.location[fragment].replace(/(?:%[a-f89][a-f0-9])+/gim, decodeURIComponent) | ||
var asyncId | ||
function debounceAsync(f) { | ||
function debounceAsync(callback) { | ||
return function() { | ||
@@ -27,5 +24,4 @@ if (asyncId != null) return | ||
asyncId = null | ||
f() | ||
callback() | ||
}) | ||
} | ||
@@ -50,12 +46,12 @@ } | ||
function getPath() { | ||
var type = prefix.charAt(0) | ||
var router = {prefix: "#!"} | ||
router.getPath = function() { | ||
var type = router.prefix.charAt(0) | ||
switch (type) { | ||
case "#": return normalize("hash").slice(prefix.length) | ||
case "?": return normalize("search").slice(prefix.length) + normalize("hash") | ||
default: return normalize("pathname").slice(prefix.length) + normalize("search") + normalize("hash") | ||
case "#": return normalize("hash").slice(router.prefix.length) | ||
case "?": return normalize("search").slice(router.prefix.length) + normalize("hash") | ||
default: return normalize("pathname").slice(router.prefix.length) + normalize("search") + normalize("hash") | ||
} | ||
} | ||
function setPath(path, data, options) { | ||
router.setPath = function(path, data, options) { | ||
var queryData = {}, hashData = {} | ||
@@ -78,16 +74,11 @@ path = parsePath(path, queryData, hashData) | ||
if (supportsPushState) { | ||
if (options && options.replace) $window.history.replaceState(null, null, prefix + path) | ||
else $window.history.pushState(null, null, prefix + path) | ||
if (options && options.replace) $window.history.replaceState(null, null, router.prefix + path) | ||
else $window.history.pushState(null, null, router.prefix + path) | ||
$window.onpopstate() | ||
} | ||
else $window.location.href = prefix + path | ||
else $window.location.href = router.prefix + path | ||
} | ||
function defineRoutes(routes, resolve, reject) { | ||
if (supportsPushState) $window.onpopstate = debounceAsync(resolveRoute) | ||
else if (prefix.charAt(0) === "#") $window.onhashchange = resolveRoute | ||
resolveRoute() | ||
router.defineRoutes = function(routes, resolve, reject) { | ||
function resolveRoute() { | ||
var path = getPath() | ||
var path = router.getPath() | ||
var params = {} | ||
@@ -114,18 +105,9 @@ var pathname = parsePath(path, params, params) | ||
} | ||
return resolveRoute | ||
if (supportsPushState) $window.onpopstate = debounceAsync(resolveRoute) | ||
else if (router.prefix.charAt(0) === "#") $window.onhashchange = resolveRoute | ||
resolveRoute() | ||
} | ||
function link(vnode) { | ||
vnode.dom.setAttribute("href", prefix + vnode.attrs.href) | ||
vnode.dom.onclick = function(e) { | ||
if (e.ctrlKey || e.metaKey || e.shiftKey || e.which === 2) return | ||
e.preventDefault() | ||
e.redraw = false | ||
var href = this.getAttribute("href") | ||
if (href.indexOf(prefix) === 0) href = href.slice(prefix.length) | ||
setPath(href, undefined, undefined) | ||
} | ||
} | ||
return {setPrefix: setPrefix, getPath: getPath, setPath: setPath, defineRoutes: defineRoutes, link: link} | ||
return router | ||
} |
@@ -17,3 +17,3 @@ "use strict" | ||
router = new Router($window) | ||
router.setPrefix(prefix) | ||
router.prefix = prefix | ||
onRouteChange = o.spy() | ||
@@ -77,3 +77,3 @@ onFail = o.spy() | ||
router = new Router($window) | ||
router.setPrefix(prefix) | ||
router.prefix = prefix | ||
@@ -289,12 +289,2 @@ router.defineRoutes({"/test": {data: 1}}, onRouteChange, onFail) | ||
}) | ||
o("replays", function() { | ||
$window.location.href = prefix + "/test" | ||
var replay = router.defineRoutes({"/test": {data: 1}}, onRouteChange, onFail) | ||
replay() | ||
o(onRouteChange.callCount).equals(2) | ||
o(onRouteChange.args).deepEquals([{data: 1}, {}, "/test", "/test"]) | ||
o(onFail.callCount).equals(0) | ||
}) | ||
}) | ||
@@ -301,0 +291,0 @@ }) |
@@ -16,3 +16,3 @@ "use strict" | ||
router = new Router($window) | ||
router.setPrefix(prefix) | ||
router.prefix = prefix | ||
onRouteChange = o.spy() | ||
@@ -19,0 +19,0 @@ onFail = o.spy() |
@@ -17,3 +17,3 @@ "use strict" | ||
router = new Router($window) | ||
router.setPrefix(prefix) | ||
router.prefix = prefix | ||
onRouteChange = o.spy() | ||
@@ -92,3 +92,3 @@ onFail = o.spy() | ||
router = new Router($window) | ||
router.setPrefix(prefix) | ||
router.prefix = prefix | ||
@@ -95,0 +95,0 @@ router.defineRoutes({"/test": {data: 1}, "/other/:a/:b...": {data: 2}}, onRouteChange, onFail) |
@@ -47,3 +47,3 @@ "use strict" | ||
var state = stream._state, parents = state.parents | ||
if (parents.length > 0 && parents.filter(active).length === parents.length && (mustSync || parents.filter(changed).length > 0)) { | ||
if (parents.length > 0 && parents.every(active) && (mustSync || parents.some(changed))) { | ||
var value = stream._state.derive() | ||
@@ -60,3 +60,3 @@ if (value === HALT) return false | ||
function combine(fn, streams) { | ||
if (streams.length > streams.filter(valid).length) throw new Error("Ensure that each item passed to m.prop.combine/m.prop.merge is a stream") | ||
if (!streams.every(valid)) throw new Error("Ensure that each item passed to m.prop.combine/m.prop.merge is a stream") | ||
return initDependency(createStream(), streams, function() { | ||
@@ -63,0 +63,0 @@ return fn.apply(this, streams.concat([streams.filter(changed)])) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
5
6
411539
3
96
10832