From 6f832a7040534961fb96bb6764dd421379d3b8b0 Mon Sep 17 00:00:00 2001 From: Leo Horie Date: Wed, 25 Mar 2015 21:54:36 -0400 Subject: [PATCH] #501,#502,#504 buildQueryString and parseQueryString fixes and tests --- mithril.js | 38 +++++++++++++++++++++++++++----------- tests/mithril-tests.js | 29 +++++++++++++++++++++++++++-- 2 files changed, 54 insertions(+), 13 deletions(-) diff --git a/mithril.js b/mithril.js index 8cd2181b..de3c06e7 100644 --- a/mithril.js +++ b/mithril.js @@ -715,28 +715,44 @@ var m = (function app(window, undefined) { else window.scrollTo(0, 0) } function buildQueryString(object, prefix) { - var str = []; - for(var prop in object) { - var key = prefix ? prefix + "[" + prop + "]" : prop, value = object[prop]; + var duplicates = {} + var str = [] + for (var prop in object) { + var key = prefix ? prefix + "[" + prop + "]" : prop + var value = object[prop] var valueType = type.call(value) - var pair = value != null && (valueType === OBJECT) ? - buildQueryString(value, key) : - valueType === ARRAY ? - value.map(function(item) {return encodeURIComponent(key + "[]") + "=" + encodeURIComponent(item)}).join("&") : - encodeURIComponent(key) + "=" + encodeURIComponent(value) - str.push(pair) + var pair = (value === null) ? encodeURIComponent(key) : + valueType === OBJECT ? buildQueryString(value, key) : + valueType === ARRAY ? value.reduce(function(memo, item) { + if (!duplicates[key]) duplicates[key] = {} + if (!duplicates[key][item]) { + duplicates[key][item] = true + return memo.concat(encodeURIComponent(key) + "=" + encodeURIComponent(item)) + } + return memo + }, []).join("&") : + encodeURIComponent(key) + "=" + encodeURIComponent(value) + if (value !== undefined) str.push(pair) } return str.join("&") } - function parseQueryString(str) { var pairs = str.split("&"), params = {}; for (var i = 0, len = pairs.length; i < len; i++) { var pair = pairs[i].split("="); - params[decodeURIComponent(pair[0])] = pair[1] ? decodeURIComponent(pair[1]) : "" + var key = decodeURIComponent(pair[0]) + var value = pair.length == 2 ? decodeURIComponent(pair[1]) : null + if (params[key] != null) { + if (type.call(params[key]) !== ARRAY) params[key] = [params[key]] + params[key].push(value) + } + else params[key] = value } return params } + m.route.buildQueryString = buildQueryString + m.route.parseQueryString = parseQueryString + function reset(root) { var cacheKey = getCellCacheKey(root); clear(root.childNodes, cellCache[cacheKey]); diff --git a/tests/mithril-tests.js b/tests/mithril-tests.js index 2bd3de83..f339f554 100644 --- a/tests/mithril-tests.js +++ b/tests/mithril-tests.js @@ -1200,7 +1200,7 @@ function testMithril(mock) { mock.requestAnimationFrame.$resolve() m.route("/test14?test&test2=") mock.requestAnimationFrame.$resolve() //teardown - return mock.location.search == "?/test14?test=&test2=" && m.route.param("test") === "" && m.route.param("test2") === "" + return mock.location.search == "?/test14?test&test2=" && m.route.param("test") === null && m.route.param("test2") === "" }) test(function() { mock.requestAnimationFrame.$resolve() //setup @@ -2264,6 +2264,31 @@ function testMithril(mock) { }) //end m.route + //m.route.parseQueryString + test(function() { + var args = m.route.parseQueryString("foo=bar&hello%5B%5D=world&hello%5B%5D=mars&hello%5B%5D=pluto") + return args["hello[]"] instanceof Array && args["hello[]"].indexOf("world") > -1 && args["hello[]"].indexOf("mars") > -1 && args["hello[]"].indexOf("pluto") > -1 + }) + test(function() { + var args = m.route.parseQueryString("foo=bar&hello=world&hello=mars&bam=&yup") + return args.foo === "bar" && args.hello[0] === "world" && args.hello[1] === "mars" && args.bam === "" && args.yup === null + }) + + //m.route.buildQueryString + test(function() { + var string = m.route.buildQueryString({ + foo: "bar", + hello: ["world", "mars", "mars"], + world: { + test:3 + }, + bam: "", + yup: null, + removed: undefined + }) + return string === "foo=bar&hello=world&hello=mars&world%5Btest%5D=3&bam=&yup" + }) + //m.prop test(function() { var prop = m.prop("test") @@ -2384,7 +2409,7 @@ function testMithril(mock) { test(function() { var prop = m.request({method: "GET", url: "test", data: {foo: [1, 2]}}) mock.XMLHttpRequest.$instances.pop().onreadystatechange() - return prop().url === "test?foo%5B%5D=1&foo%5B%5D=2" + return prop().url === "test?foo=1&foo=2" }) // m.request over jsonp