diff --git a/docs/buildQueryString.md b/docs/buildQueryString.md new file mode 100644 index 00000000..23d855a5 --- /dev/null +++ b/docs/buildQueryString.md @@ -0,0 +1,40 @@ +# buildQueryString(object) + +- [API](#api) +- [How it works](#how-it-works) + +--- + +### API + +`querystring = m.buildQueryString(object)` + +Argument | Type | Required | Description +------------ | ------------------------------------------ | -------- | --- +`object` | `Object` | Yes | A key-value map to be converted into a string +**returns** | `String` | | A string representing the input object + +[How to read signatures](signatures.md) + +--- + +### How it works + +The `m.buildQueryString` creates a querystring from an object. It's useful for manipulating URLs + +```javascript +var querystring = m.buildQueryString({a: 1, b: 2}) + +// querystring is "a=1&b=2" +``` + +#### Deep data structures + +Deep data structures are serialized in a way that is understood by popular web application servers such as PHP, Rails and ExpressJS + +```javascript +var querystring = m.buildQueryString({a: ["hello", "world"]}) + +// querystring is "a[0]=hello&a[1]=world" +``` + diff --git a/docs/parseQueryString.md b/docs/parseQueryString.md new file mode 100644 index 00000000..9d159c35 --- /dev/null +++ b/docs/parseQueryString.md @@ -0,0 +1,59 @@ +# parseQueryString(string) + +- [API](#api) +- [How it works](#how-it-works) + +--- + +### API + +`object = m.parseQueryString(string)` + +Argument | Type | Required | Description +------------ | ------------------------------------------ | -------- | --- +`string` | `String` | Yes | A querystring +**returns** | `Object` | | A key-value map + +[How to read signatures](signatures.md) + +--- + +### How it works + +The `m.parseQueryString` method creates an object from a querystring. It is useful for handling data from URL + +```javascript +var data = m.parseQueryString("a=hello&b=world") + +// data is {a: "hello", b: "world"} +``` + +#### Boolean type casting + +This method attempts to cast boolean values if possible. This helps prevents bugs related to loose truthiness and unintended type casts. + +```javascript +var data = m.parseQueryString("a=true&b=false") + +// data is {a: true, b: false} +``` + +#### Leading question mark tolerance + +For convenience, the `m.parseQueryString` method ignores a leading question mark, if present: + +```javascript +var data = m.parseQueryString("?a=hello&b=world") + +// data is {a: "hello", b: "world"} +``` + +#### Deep data structures + +Querystrings that contain bracket notation are correctly parsed into deep data structures + +```javascript +m.parseQueryString("a[0]=hello&a[1]=world") + +// data is {a: ["hello", "world"]} +``` \ No newline at end of file diff --git a/docs/request.md b/docs/request.md index 6ab13da3..df862038 100644 --- a/docs/request.md +++ b/docs/request.md @@ -32,7 +32,7 @@ Argument | Type | Required | Descript `options.type` | `any = Function(any)` | No | A constructor to be applied to each object in the response. Defaults to the [identity function](https://en.wikipedia.org/wiki/Identity_function). `options.serialize` | `string = Function(any)` | No | A serialization method to be applied to `data`. Defaults to `JSON.stringify`, or if `options.data` is an instance of [`FormData`](https://developer.mozilla.org/en/docs/Web/API/FormData), defaults to the [identity function](https://en.wikipedia.org/wiki/Identity_function) (i.e. `function(value) {return value}`). `options.deserialize` | `any = Function(string)` | No | A deserialization method to be applied to the response. Defaults to a small wrapper around `JSON.parse` that returns `null` for empty responses. -`options.extract` | `string = Function(xhr, options)` | No | A hook to specify how the XMLHttpRequest response should be read. Useful for reading response headers and cookies. Defaults to a function that returns `xhr.responseText`. If defined, `options.deserialize` is ignored. +`options.extract` | `string = Function(xhr, options)` | No | A hook to specify how the XMLHttpRequest response should be read. Useful for reading response headers and cookies. Defaults to a function that returns `xhr.responseText`. If defined, the `xhr` parameter is the XMLHttpRequest instance used for the request, and `options` is the object that was passed to the `m.request` call. If a custom `extract` callback is set, `options.deserialize` is ignored. `options.initialValue` | `any` | No | A value to populate the returned stream before the request completes `options.useBody` | `Boolean` | No | Force the use of the HTTP body section for `data` in `GET` requests when set to `true`, or the use of querystring for other HTTP methods when set to `false`. Defaults to `false` for `GET` requests and `true` for other methods. **returns** | `Stream` | | A stream that resolves to the response data, after it has been piped through the `extract`, `deserialize` and `type` methods diff --git a/querystring/parse.js b/querystring/parse.js index 9581393e..287ec0da 100644 --- a/querystring/parse.js +++ b/querystring/parse.js @@ -10,10 +10,7 @@ module.exports = function(string) { var key = decodeURIComponent(entry[0]) var value = entry.length === 2 ? decodeURIComponent(entry[1]) : "" - //TODO refactor out - var number = Number(value) - if (value !== "" && !isNaN(number) || value === "NaN") value = number - else if (value === "true") value = true + if (value === "true") value = true else if (value === "false") value = false var levels = key.split(/\]\[?|\[/) diff --git a/querystring/tests/test-parseQueryString.js b/querystring/tests/test-parseQueryString.js index 3325d19a..dd9d2a9c 100644 --- a/querystring/tests/test-parseQueryString.js +++ b/querystring/tests/test-parseQueryString.js @@ -72,13 +72,13 @@ o.spec("parseQueryString", function() { var data = parseQueryString("a=true&b=false") o(data).deepEquals({a: true, b: false}) }) - o("casts numbers", function() { + o("does not cast numbers", function() { var data = parseQueryString("a=1&b=-2.3&c=0x10&d=1e2&e=Infinity") - o(data).deepEquals({a: 1, b: -2.3, c: 16, d: 100, e: Infinity}) + o(data).deepEquals({a: "1", b: "-2.3", c: "16", d: "1e2", e: "Infinity"}) }) - o("casts NaN", function() { + o("does not cast NaN", function() { var data = parseQueryString("a=NaN") - o(isNaN(data.a)).equals(true) + o(data.a).equals("NaN") }) o("does not casts Date", function() { var data = parseQueryString("a=1970-01-01") diff --git a/tests/test-api.js b/tests/test-api.js index 3c91606e..e8e24260 100644 --- a/tests/test-api.js +++ b/tests/test-api.js @@ -156,7 +156,8 @@ o.spec("api", function() { done() }, FRAME_BUDGET) }) - o("m.route.set", function(done) { + o("m.route.set", function(done, timeout) { + timeout(100) var root = window.document.createElement("div") m.route(root, "/a", { "/:id": {view: function() {return m("div")}}