Comparing version
{ | ||
"name": "corridor", | ||
"version": "0.1.3", | ||
"version": "0.1.4", | ||
"description": "JSON/DOM data corridor for data-binding", | ||
@@ -17,3 +17,9 @@ "repository": { | ||
"license": "MIT", | ||
"readmeFilename": "README.md" | ||
"readmeFilename": "README.md", | ||
"scripts": { | ||
"test": "./node_modules/nodeunit/bin/nodeunit ./test" | ||
}, | ||
"devDependencies": { | ||
"nodeunit": "~0.8.1" | ||
} | ||
} |
# corridor | ||
JSON/DOM data corridor. | ||
Data binding without the fuss. | ||
**{json} → <html> → {json}** | ||
Bi-directional data binding without the fuss. | ||
## why corridor | ||
Your data is in JSON, but your users interact with HTML. | ||
corridor's singular mission is to shuttle your data between your JSON and your HTML. | ||
It is a runtime library, not a templating language. | ||
corridor runs in the browser, able to transfer your data both ways: from form fields to JSON and back again. | ||
## getting corridor | ||
corridor is just a single js file. | ||
corridor is a single js file with no dependencies. | ||
You can get it in either of two ways: | ||
@@ -17,9 +27,15 @@ * from github: grab [corridor.js](https://github.com/jimbojw/corridor/blob/master/src/corridor.js) out of the [corridor repo](https://github.com/jimbojw/corridor) | ||
## using corridor | ||
## corridor tutorial | ||
It would be great if users could just edit JSON directly. | ||
That way, your REST API would be all you'd need. | ||
But unfortunately, your users interact with the Document Object Model (DOM) representation of your HTML. | ||
Which means that it's your job to figure out how to get these two views of the data to match. | ||
The corridor library has only one function called `corridor()`. | ||
This function does one of two things: | ||
* extract data out of a DOM heirarchy, or | ||
* insert data into a DOM heirarchy. | ||
* extract data out of a DOM heirarchy (form elements), or | ||
* insert data into the DOM. | ||
@@ -212,4 +228,45 @@ It knows how to shuttle data back and forth by looking at HTML5 data attributes on the DOM elements. | ||
## issues and feature requests | ||
If you find any issues with corridor, or if you'd like to request a feature, please head over to the [issues page on github](https://github.com/jimbojw/corridor/issues). | ||
Keep in mind that the more specific you are, the more likely your issue or feature is to be addressed. | ||
## questions | ||
If you have a question about how to use corridor, or if you're not sure if you're doing it right, go to [stackoverflow](http://stackoverflow.com/) and [ask a question](http://stackoverflow.com/questions/ask?tags=corridor). | ||
Make sure you add the `corridor` tag to your question. | ||
## developing corridor | ||
If you're interested in developing corridor, great! | ||
Start by forking [corridor on github](https://github.com/jimbojw/corridor). | ||
Once you've forked the project, clone it using `git clone`: | ||
```sh | ||
$ git clone git@github.com:<YOUR_USERNAME>/corridor.git | ||
``` | ||
corridor uses npm for packaging and deployment, so you'll need to install Node.js if you haven't already. | ||
Once you have node, you can pull in corridor's development dependencies: | ||
```sh | ||
$ npm install | ||
``` | ||
After installing the dependencies, you can run the unit tests: | ||
```sh | ||
$ npm test | ||
``` | ||
The source code for corridor is in the `src/` directory, and unit tests are under `test/`. | ||
corridor's unit tests are written for [nodeunit](https://npmjs.org/package/nodeunit). | ||
When you're satisfied with your changes, commit them and push them to your forked repository. | ||
Then open a pull request in github by hitting the big "Pull Request" button from the main project repo page. | ||
## License | ||
See LICENSE |
/** | ||
* corridor.js | ||
* | ||
* corridor is written to run in either a Node.js context or a browser context. | ||
* The context and property objects are used to know how to export corridor. | ||
* | ||
* @param {mixed} context The context object (either module or window) | ||
* @param {string} property The name of the key to assign on the context object (either 'exports' or 'corridor') | ||
*/ | ||
(function(window, document, undefined){ | ||
(function(context, property, undefined){ | ||
'use strict'; | ||
@@ -12,2 +18,4 @@ | ||
document = context.document || null, | ||
/** | ||
@@ -28,9 +36,10 @@ * Internal logging function. | ||
/** | ||
* Extract data from DOM or insert values back into it. | ||
* @param {HTMLElement} elem The element to scan for data (defaults to document) | ||
* Extract data from the DOM or insert values back into it. | ||
* @param {HTMLElement} root The element to scan for data (defaults to document) | ||
* @param {mixed} data The data to insert (optional) | ||
* @param {object} opts Hash of options (optional) | ||
*/ | ||
corridor = window['corridor'] = function(elem, data) { | ||
elem = elem || document; | ||
return data ? insert(elem, data) : extract(elem); | ||
corridor = context[property] = function(root, data, opts) { | ||
root = root || document; | ||
return data ? insert(root, data, opts) : extract(root, opts); | ||
}, | ||
@@ -41,33 +50,43 @@ | ||
* @param {HTMLElement} root The root element to scan for data. | ||
* @param {object} opts Hash of options (optional) | ||
*/ | ||
extract = corridor.extract = function(root) { | ||
extract = corridor.extract = function(root, opts) { | ||
root = root || document; | ||
var data = {}; | ||
// fail fast if there's no root element to use | ||
if (!root) { | ||
throw Error('corridor requires a queryable root element to insert data into'); | ||
} | ||
var | ||
settings = extend({}, defaults, opts), | ||
data = {}, | ||
fields = slice.call(root.querySelectorAll('[data-field]')).filter(hasVal); | ||
slice.call(root.querySelectorAll('[data-field]')) | ||
.filter(hasVal) | ||
.filter(enabled) | ||
.forEach(function(elem) { | ||
if (settings.enabledOnly) { | ||
fields = fields.filter(enabled); | ||
} | ||
var | ||
opts = options(elem, defaults), | ||
value = val(elem); | ||
if (opts.empty === 'omit' && !value) { | ||
return; | ||
} | ||
// create type-specific value string | ||
value = JSON.stringify(coerce(value, opts.type, opts)); | ||
// build out full contribution | ||
value = buildup(value, elem, root); | ||
// merge contribution into the result data | ||
merge(data, JSON.parse(value)); | ||
}); | ||
fields.forEach(function(elem) { | ||
var | ||
opts = options(elem, settings), | ||
value = val(elem); | ||
if (opts.empty === 'omit' && !value) { | ||
return; | ||
} | ||
// create type-specific value string | ||
value = JSON.stringify(coerce(value, opts.type, opts)); | ||
// build out full contribution | ||
value = buildup(value, elem, root); | ||
// merge contribution into the result data | ||
merge(data, JSON.parse(value)); | ||
}); | ||
return data; | ||
@@ -79,15 +98,31 @@ | ||
* Insert data into the DOM under the specified element from provided data. | ||
* @param {HTMLElement} root The element to scan for insertion fields. | ||
* @param {HTMLElement} root The element to scan for insertion fields (optional). | ||
* @param {mixed} data The data to insert. | ||
*/ | ||
insert = corridor.insert = function(root, data) { | ||
insert = corridor.insert = function(root, data, opts) { | ||
// data structure for existing fields | ||
// used to figure out true contribution paths for inserting data into elements | ||
var workspace = {}; | ||
// allow root to be optional | ||
root = root || document; | ||
// fail fast if there's no root element to use | ||
if (!root) { | ||
throw Error('corridor requires a queryable root element to insert data into'); | ||
} | ||
var | ||
settings = extend({}, defaults, opts), | ||
// data structure for existing fields | ||
// used to figure out true contribution paths for inserting data into elements | ||
workspace = {}, | ||
fields = slice.call(root.querySelectorAll('[data-field]')).filter(hasVal); | ||
if (settings.enabledOnly) { | ||
fields = fields.filter(enabled); | ||
} | ||
// for each value'd, enabled data-field | ||
slice.call(root.querySelectorAll('[data-field]')) | ||
.filter(hasVal) | ||
.filter(enabled) | ||
fields | ||
.map(function(elem) { | ||
@@ -110,3 +145,3 @@ | ||
var | ||
opts = options(elem, defaults), | ||
opts = options(elem, settings), | ||
node = workspace; | ||
@@ -148,3 +183,3 @@ while (pathCopy.length > 1) { | ||
/** | ||
* Default values applied to data-opts. | ||
* Default values applied to options. | ||
*/ | ||
@@ -179,4 +214,9 @@ defaults = corridor.defaults = { | ||
*/ | ||
type: "string" | ||
type: "string", | ||
/** | ||
* Only operate on enabled fields when this is true (the default). | ||
*/ | ||
enabledOnly: true | ||
}, | ||
@@ -522,2 +562,4 @@ | ||
})(window, document); | ||
}).apply(null, | ||
typeof module === 'object' ? [module, 'exports'] : [window, 'corridor'] | ||
); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
54718
8.91%11
10%1024
4.38%271
26.64%1
Infinity%