Socket
Socket
Sign inDemoInstall

corridor

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

corridor - npm Package Compare versions

Comparing version 0.1.4 to 0.2.0

test/test-convertname.js

2

package.json
{
"name": "corridor",
"version": "0.1.4",
"version": "0.2.0",
"description": "JSON/DOM data corridor for data-binding",

@@ -5,0 +5,0 @@ "repository": {

@@ -41,4 +41,2 @@ # corridor

It knows how to shuttle data back and forth by looking at HTML5 data attributes on the DOM elements.
Let's take a look at how this works by using the practical example of a [`package.json`](https://npmjs.org/doc/json.html) file.

@@ -51,3 +49,3 @@ We'll build out a single-page web app for manipulating a package.json file.

For a `package.json`, you need at least the following data:
For a `package.json` file, you need at least the following data:

@@ -77,3 +75,2 @@ * name - the name of the project.

corridor makes it easy to write a UI that controls this data structure.
Let's start with the `name` field.

@@ -83,11 +80,7 @@ Here's the HTML you'd need:

```html
<input type="text" data-field='{"name":$$$}' />
<input type="text" name="name" />
```
The `data-field` attribute tells corridor that this `input` provides the value for the `name` property.
The `$$$` token is necessary here, it tells corridor how to insert the value.
Other than the `$$$` token, the `data-field` should contain proper JSON.
Let's try it out.
Make sure you have the `<input>` HTML on a page and the corridor library included.
Make sure you have the `<input>` HTML on a page and the `corridor.js` library included.
Then you can call the corridor function with no arguments to extract all the data on the page.

@@ -107,13 +100,13 @@

All options to corridor are done by adding a `data-opts` attribute to the node.
To give options to corridor for a particular HTML element, give it a `data-opts` attribute.
Let's see how this applies to the `keywords` field of a package.json.
The corridor HTML for the keywords field looks like this:
The HTML for the keywords field should look like this:
```html
<textarea data-field='{"keywords":$$$}' data-opts='{"type":"list"}'></textarea>
<textarea name="keywords" data-opts='{"type":"list"}'></textarea>
```
Here the `type` property indicates that we have a `list` value.
corridor will try to parse the text value of the `<textarea>` as a list of items, and will output an array.
corridor will try to parse the text in the `<textarea>` as a list of items, and will output an array.

@@ -152,6 +145,6 @@ Let's give it a try!

```html
<p data-field='{"dependencies":$$$}'>
<fieldset>
<label>
foo:
<select data-field='{"foo":$$$}'>
<select name="dependencies.foo">
<option value="~1.1.0">foo: version 1</option>

@@ -163,3 +156,3 @@ <option value="~2.0.0">foo: version 2</option>

bar:
<select data-field='{"bar":$$$}'>
<select name="dependencies.bar">
<option value="~3.5.0">bar: version 3</option>

@@ -172,4 +165,2 @@ <option value="~4.1.0">bar: version 4</option>

The paragraph element's `data-field` attribute tells corridor that any fields under it should roll up under it when creating the data object.
Running `corridor()` on this gives us:

@@ -186,5 +177,107 @@

But it doesn't end there!
Since both the `foo` and `bar` select boxes live under `dependencies`, giving a `name` to the fieldset would have the same effect:
```html
<fieldset name="dependencies">
<label>
foo:
<select name="foo">
<option value="~1.1.0">foo: version 1</option>
<option value="~2.0.0">foo: version 2</option>
</select>
</label>
<label>
bar:
<select name="bar">
<option value="~3.5.0">bar: version 3</option>
<option value="~4.1.0">bar: version 4</option>
</select>
</label>
</p>
```
If you run corridor in this, you'll get the same JSON listed above.
Merging works best for objects like the `dependencies` object we just looked at.
But corridor can also merge arrays.
### rich path names
In the last section we saw a rudimentary example of how to create nested data structures.
The range of supported names is quite rich.
These are best explained by example.
Let's say you wanted to add `authors` to your package.json form, with a separate input for each author.
The HTML for that might look like this:
```html
<fieldset>
<label>
first author:
<input type="text" name="authors[]" value="your name" />
</label>
<label>
second author:
<input type="text" name="authors[]" data-opts='{"empty":"omit"}' />
</label>
<label>
third author:
<input type="text" name="authors[]" data-opts='{"empty":"omit"}' />
</label>
</fieldset>
```
The name attribute for each author input is `authors[]`.
The trailing square brackets means that the input value should contribute to an array.
Running corridor on the above would give you JSON like this:
```js
{
authors: [
"your name"
]
}
```
Notice that there's only one element in this array.
That's due to the `empty:omit` option on each of the other inputs.
By default, corridor will include empty values in the output JSON it produces, but you can disable this feature by setting `empty` to `omit`.
Just like with the `dependencies.foo` case from last section, here we could split up the parts of the name between the fieldset and the inputs.
E.g.
```html
<fieldset name="authors">
<label>
first author:
<input type="text" name="[]" value="your name" />
```
You can mix and match dot delimited paths and square brackets to create even richer structures.
```html
<input type="text" name="stock.ticker[]symbols" value="BCOV AMZN" data-opts='{"type":"list"}' />
```
Produces this:
```js
"stock": {
"ticker": [
{
"symbols": [
"BCOV",
"AMZN"
]
}
]
}
```
Whitespace around key names is stripped, but whitespace inside them is preserved.
For example `name=" foo bar "` would produce an object with a `foo bar` property.
### toggling sections

@@ -195,6 +288,6 @@

For example, say you wanted a checkbox to control whether `keywords` were going to be included in the output.
The corridor HTML for that might look like this:
The HTML for that might look like this:
```html
<div data-opts='{"role":"toggleable"}'>
<fieldset data-opts='{"role":"toggleable"}'>
<p>

@@ -209,18 +302,17 @@ <label>

keywords (list format):
<textarea data-field='{"keywords":$$$}' data-opts='{"type":"list"}'></textarea>
<textarea name="keywords" data-opts='{"type":"list"}'></textarea>
</label>
</p>
</div>
</fieldset>
```
Adding the `toggleable` role to the outer `<div>` signals to corridor that this section can be turned on and off.
Adding the `toggleable` role to the `<frameset>` signals to corridor that this section can be turned on and off.
The checkbox with the role `toggle` controls it.
You can nest toggleable sections inside each other.
In each case, the toggle that control the toggleable container is the nearest child.
In each case, the toggle that controls the toggleable container is the nearest child.
### inserting data
Just as corridor can pull data out of the DOM, it can put the data back in as well.
This feature is still a bit experimental, there are some bugs around reinserting arrays (we're working on it).
This tutorial has focused largely on explaining how data flows from HTML to JSON, but corridor is great at sending data the other way as well.

@@ -236,3 +328,3 @@ To insert data back into the DOM, call the corridor function with a root element and a data structure object.

corridor uses the same `data-field` and `data-opts` parameters to determine where data values should be inserted.
corridor uses the same `name` and `data-opts` attributes to determine where data values should be inserted.

@@ -239,0 +331,0 @@ ## issues and feature requests

@@ -39,2 +39,5 @@ /**

* @param {object} opts Hash of options (optional)
* Relevant options are:
* - enabledOnly - Whether to only include enabled elements
* - namedFields - Whether to include fields with a 'name' attribute
*/

@@ -49,3 +52,3 @@ corridor = context[property] = function(root, data, opts) {

* @param {HTMLElement} root The root element to scan for data.
* @param {object} opts Hash of options (optional)
* @param {object} opts Hash of options (optional, see corridor options)
*/

@@ -64,3 +67,3 @@ extract = corridor.extract = function(root, opts) {

data = {},
fields = slice.call(root.querySelectorAll('[data-field]')).filter(hasVal);
fields = selectFields(root, settings).filter(hasVal);

@@ -100,2 +103,3 @@ if (settings.enabledOnly) {

* @param {mixed} data The data to insert.
* @param {object} opts Hash of options (optional, see corridor options)
*/

@@ -120,3 +124,3 @@ insert = corridor.insert = function(root, data, opts) {

fields = slice.call(root.querySelectorAll('[data-field]')).filter(hasVal);
fields = selectFields(root, settings).filter(hasVal);

@@ -216,9 +220,31 @@ if (settings.enabledOnly) {

/**
* Only operate on enabled fields when this is true (the default).
* When inserting/extracting, only operate on enabled fields (default: true).
*/
enabledOnly: true
enabledOnly: true,
/**
* When selecting fields, include any elements with a 'name' attribute (default: true).
*/
namedFields: true
},
/**
* Select an array of field elements from the specified root element.
* @param {HTMLElement} root The root element to search for fields.
* @param {object} opts Options hash to affect selection behavior (optional).
* Relevant options are:
* - namedFields - Whether to include elements with a 'name' attribute
*/
selectFields = corridor.selectFields = function(root, opts) {
var
settings = extend({}, defaults, opts),
selector = '[data-field]' + (settings.namedFields ? ', [name]' : '');
return slice.call(root.querySelectorAll(selector));
},
/**
* Visit each corridor ancestor element up from the specified starting node.

@@ -242,6 +268,15 @@ * An element is a corridor element if it has a data-field or data-opts attribute.

upwalk = corridor.upwalk = function(elem, root, callback) {
var field, opts, res;
while (elem !== null && elem.getAttribute) {
if (elem.hasAttribute('data-field') || elem.hasAttribute('data-opts')) {
field = undefined;
if (elem.hasAttribute('data-field')) {
field = elem.getAttribute('data-field') || undefined;
} else if (elem.hasAttribute('name')) {
field = convertName(elem.getAttribute('name'));
}
if (field || elem.hasAttribute('data-opts')) {
opts = options(elem, defaults);

@@ -253,8 +288,50 @@ res = callback(elem, field, opts);

}
elem = (elem === root) ? null : elem.parentNode;
}
return true;
},
/**
* Convert a simple name attribute string into a full field string.
* The simple name format is a hybrid of Apple's Key-Value Coding and PHP's array-based form variables.
*
* Examples:
* - 'foo' --> '{"foo":$$$}'
* - 'foo.bar' --> '{"foo":{"bar":$$$}}'
* - '[]' --> '[$$$]'
* - 'list[]' --> 'list[$$$]'
* - 'foo[bar]' --> '{"foo":{"bar":$$$}}'
* - 'foo[bar][]' --> '{"foo":{"bar":[$$$]}}'
*
* @see https://developer.apple.com/library/ios/DOCUMENTATION/Cocoa/Conceptual/KeyValueCoding/Articles/BasicPrinciples.html
* @see http://php.net/manual/en/faq.html.php#faq.html.arrays
*
* @param {string} name The name string to convert.
* @return {string} The full field string.
*/
convertName = corridor.convertName = function(name) {
var field = "\ufff0"; // start out with the target mark
name
.replace(/^\s+|\s+$/g, '') // trim whitespace for courtesy
.replace(/\[\s+]/g, '[]') // trim inside bracket vars
.replace(/\[([^\]]+)]/g, '.$1') // convert bracket vars to dot vars
.match(/[^[\].]+|\[\]/g) // grab list of component parts
.forEach(function(p) {
p = p.replace(/^\s+|\s+$/g, ''); // trim each part
field = field.replace("\ufff0", // add part to field specification
p === '[]' ? "[\ufff0]" : "{" + JSON.stringify(p || 'undefined') + ":\ufff0}"
);
});
return field.replace("\ufff0", '$$$$$$');
},
/**
* Walk up the parent chain and perform replacements to build up full contribution.

@@ -394,3 +471,3 @@ * @param {string} value Starting value, must be a string.

listify = corridor.listify = function(arry) {
if (toString.call(arry) !== '[abject Array]') {
if (toString.call(arry) !== '[object Array]') {
return arry;

@@ -436,2 +513,3 @@ }

if (!candidates.length) {
log('No child "toggle" element found for toggelable.', elem);
throw Error('No child "toggle" element found for toggelable.');

@@ -441,2 +519,3 @@ }

if (candidates.length > 1) {
log('Multiple "toggle" elements have been found for toggleable.', elem);
throw Error('Multiple "toggle" elements have been found for toggleable.');

@@ -443,0 +522,0 @@ }

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc