Skip to content

Commit 16904da

Browse files
committed
First commit - basically working version.
0 parents  commit 16904da

12 files changed

+1281
-0
lines changed

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# bower components
2+
bower_components
3+
4+
# Compiled binary addons (http://nodejs.org/api/addons.html)
5+
build/Release
6+
7+
# Dependency directory
8+
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
9+
node_modules

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2017 GerhardHH
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# e2u-json-object-editor
2+
3+
A simple object editor based on JSON schema by [GerhardHH](https://github.com/GerhardHH)
4+
5+
`e2u-json-object-editor` takes in a JSON schema of type object and builds a form,
6+
exposing a `value` property that represents an object described by the schema.
7+
JSON schema is defined here: http://json-schema.org/
8+
It is inspired by `eco-json-schema-object`, see
9+
http://ecoutu.github.io/eco-json-schema-form/components/eco-json-schema-form/.
10+
11+
However, while trying to modify this to achieve editablility for a given value,
12+
I found it might be possible to simplify the component by reducing it to the
13+
basic needs and change the data binding.
14+
15+
For more information, see the code and the demo which provides code comments.
16+
17+
## Installation
18+
19+
First, make sure you have the [Polymer CLI](https://www.npmjs.com/package/polymer-cli)
20+
and bower (https://bower.io/) installed.
21+
22+
After git clone, perform the following steps:
23+
24+
- run `bower install` to download dependent modules
25+
- then run `polymer serve` to serve your application locally.
26+
27+
See the displayed URL and open it in your browser. Alternatively, you may
28+
call `polymer serve --open`
29+
30+
## Usage
31+
You may incorporate the element into your page like:
32+
```
33+
<e2u-json-object-editor
34+
schema="[[schema]]" value="{{value}}"
35+
label="Energy2use JSON schema object editor">
36+
</e2u-json-object-editor>
37+
```
38+
## Contributing
39+
1. Fork it!
40+
2. Create your feature branch: `git checkout -b my-new-feature`
41+
3. Commit your changes: `git commit -am 'Add some feature'`
42+
4. Push to the branch: `git push origin my-new-feature`
43+
5. Submit a pull request :D
44+
45+
## History
46+
2017-02-15: Initial version
47+
## Credits
48+
Thanks to Eric Coutu <eric.coutu@gmail.com> for his eco-json-schema-form project,
49+
which inspired me for this: https://github.com/ecoutu/eco-json-schema-form
50+
## License
51+
MIT license, see LICENSE

all-imports.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<link rel="import" href="./e2u-behaviors.html">
2+
<link rel="import" href="./e2u-json-object-editor.html">
3+
<link rel="import" href="./e2u-json-array-editor.html">
4+
<link rel="import" href="./e2u-test-editor.html">

bower.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"name": "e2u-json-object-editor",
3+
"description": "A simple Polymer object editor based on JSON schema",
4+
"main": "e2u-json-object-editor.html",
5+
"license": "MIT",
6+
"authors": [
7+
"Gerhard Höger-Hansen <info@friendlygis.com> (http://www.friendlygis.com)"
8+
],
9+
"keywords": ["Polymer","autoform","JSON Schema"],
10+
"dependencies": {
11+
"polymer": "Polymer/polymer#^1.4.0",
12+
"iron-flex-layout": "^1.3.1",
13+
"paper-input": "^1.1.23"
14+
},
15+
"devDependencies": {
16+
"iron-component-page": "PolymerElements/iron-component-page#^1.0.0",
17+
"iron-demo-helpers": "PolymerElements/iron-demo-helpers#^1.0.0",
18+
"web-component-tester": "^4.0.0",
19+
"webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0"
20+
}
21+
}

demo/index.html

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes">
6+
7+
<title>e2u-json-object-editor demo</title>
8+
9+
<script src="../../webcomponentsjs/webcomponents-lite.js"></script>
10+
11+
<link rel="import" href="../../iron-demo-helpers/demo-pages-shared-styles.html">
12+
<link rel="import" href="../../iron-demo-helpers/demo-snippet.html">
13+
<link rel="import" href="../all-imports.html">
14+
15+
<style is="custom-style" include="demo-pages-shared-styles">
16+
</style>
17+
</head>
18+
<body>
19+
<e2u-test-editor></e2u-test-editor>
20+
</body>
21+
</html>

e2u-behaviors.html

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
<!--
2+
Defines behaviors usable for Energy2Use (namespace e2uBehaviors).
3+
4+
Especially, holds methods to create GUI elements for the array
5+
elements and helpers to handle the JSON schema.
6+
7+
8+
9+
-->
10+
11+
<script>
12+
// initialize behavior namespace if it not yet exists
13+
window.E2uBehaviors = window.E2uBehaviors || {};
14+
//console.log('Init behavior E2uBehaviors');
15+
/**
16+
* This behavior holds all code to read a JSON schema.
17+
*/
18+
/** @polymerBehavior E2uBehaviors.JSONSchema */
19+
E2uBehaviors.JSONSchema = {
20+
created: function() {
21+
//console.log("Behavior created");
22+
},
23+
registered: function() {
24+
//console.log("Behavior registered");
25+
},
26+
getArrayKey: function getArrayKey(myArray, myIndex) {
27+
var collection = Polymer.Collection.get(myArray);
28+
var keyIndexHash = collection.getKey(myArray[myIndex]);
29+
return keyIndexHash;
30+
},
31+
getArrayIndex: function getArrayIndex(myArray, myKey) {
32+
var collection = Polymer.Collection.get(myArray);
33+
var item = collection.getItem(myKey);
34+
var index = myArray.indexOf(item);
35+
return index;
36+
},
37+
/**
38+
* Create an element to be inserted into the generated form.
39+
* @parameter schemaProperty
40+
* An object describing how to create the element. It must have the following properties:
41+
* - property - a property name (path) representing the current property in an underlying object
42+
* For arrays, we have the value of the $arrKey property in the array elements.
43+
* - schema - the JSON schema describing the value to be created
44+
* - component - describe the component to be used, with name=component name and
45+
* valueProperty=property to set the value on the element
46+
*/
47+
_createElement: function createElement(schemaProperty) {
48+
var ctx = this;
49+
var pName = schemaProperty.property;
50+
var cName = schemaProperty.component.name;
51+
var schema = schemaProperty.schema;
52+
//var eleProps =
53+
var el = ctx.create(cName, {
54+
label: schemaProperty.label
55+
});
56+
if (cName == 'e2u-json-object-editor') {
57+
// if we have an object, add the schema information.
58+
el.schema = schema;
59+
el.schemaProperty = schemaProperty;
60+
el._level += 1;
61+
el.setAttribute('style', 'margin-left:' + el._level * 10 + 'px');
62+
el.addEventListener('value-changed', ctx._objectUp('value.' + pName, el));
63+
} else if (cName == 'e2u-json-array-editor') {
64+
// if we have an array, add the schema information.
65+
el.schema = schema;
66+
el.schemaProperty = schemaProperty;
67+
el._level += 1;
68+
el.setAttribute('style', 'margin-left:' + el._level * 10 + 'px');
69+
el.addEventListener('value-changed', ctx._objectUp('value.' + pName, el));
70+
} else {
71+
// else set id to the property name and set an eventlistener to
72+
// use the valueUp() method which sets the subproperty.
73+
el.setAttribute('id', pName);
74+
el.addEventListener('value-changed', ctx._valueUp('value.' + pName));
75+
// Since we are editing a simple property, we check for
76+
var inputEl = el.$.input;
77+
inputEl.setAttribute('onfocusout', 'validate()');
78+
if (this._isSchemaNumber(schema.type)) {
79+
inputEl.type = 'number';
80+
81+
if (schema.multipleOf) {
82+
inputEl.step = schema.multipleOf;
83+
}
84+
85+
if (!isNaN(schema.maximum)) {
86+
if (schema.exclusiveMaximum) {
87+
inputEl.max = schema.maximum - (schema.multipleOf || 1);
88+
} else {
89+
inputEl.max = schema.maximum;
90+
}
91+
}
92+
93+
if (!isNaN(schema.minimum)) {
94+
if (schema.exclusiveMinimum) {
95+
inputEl.min = schema.minimum + (schema.multipleOf || 1);
96+
} else {
97+
inputEl.min = schema.minimum;
98+
}
99+
}
100+
}
101+
102+
if (this._isSchemaString(schema.type)) {
103+
if (schema.format === 'date-time') {
104+
inputEl.type = 'datetime-local';
105+
inputEl.alwaysFloatLabel = true; // label doesn't float when value not set
106+
} else if (schema.format === 'date') {
107+
inputEl.type = 'date';
108+
} else if (schema.format === 'email') {
109+
inputEl.type = 'email';
110+
} else if (schema.format === 'hostname') {
111+
inputEl.type = 'text';
112+
} else if (schema.format === 'ipv4') {
113+
inputEl.type = 'text';
114+
} else if (schema.format === 'ipv6') {
115+
inputEl.type = 'text';
116+
} else if (schema.format === 'uri') {
117+
inputEl.type = 'url';
118+
} else {
119+
inputEl.type = 'text';
120+
}
121+
122+
if (schema.maxLength || schema.minLength) {
123+
inputEl.charCounter = true;
124+
}
125+
126+
if (schema.maxLength) {
127+
inputEl.maxlength = schema.maxLength;
128+
}
129+
130+
if (schema.minLength) {
131+
inputEl.minlength = schema.minLength;
132+
}
133+
134+
if (schema.pattern) {
135+
inputEl.pattern = schema.pattern;
136+
}
137+
}
138+
139+
if (schema.component && schema.component.properties) {
140+
Object.keys(schema.component.properties).forEach(function(prop) {
141+
inputEl[prop] = schema.component.properties[prop];
142+
});
143+
}
144+
145+
if (schema.title) {
146+
inputEl.label = schema.title;
147+
}
148+
}
149+
return el;
150+
},
151+
_deepClone: function(o) {
152+
return JSON.parse(JSON.stringify(o));
153+
},
154+
/* Is the schema fragment representing an enumeration? */
155+
_isSchemaEnum: function(schema) {
156+
return !!schema.enum;
157+
},
158+
/* Is the schema fragment representing a simple value? */
159+
_isSchemaValue: function(type) {
160+
return this._isSchemaBoolean(type) || this._isSchemaNumber(type) || this._isSchemaString(type);
161+
},
162+
/* Is the schema fragment representing a boolean? */
163+
_isSchemaBoolean: function(type) {
164+
if (Array.isArray(type)) {
165+
return type.indexOf('boolean') !== -1;
166+
} else {
167+
return type === 'boolean';
168+
}
169+
},
170+
_isSchemaNumber: function(type) {
171+
if (Array.isArray(type)) {
172+
return type.indexOf('number') !== -1 || type.indexOf('integer') !== -1;
173+
} else {
174+
return type === 'number' || type === 'integer';
175+
}
176+
},
177+
_isSchemaString: function(type) {
178+
if (Array.isArray(type)) {
179+
return type.indexOf('string') !== -1;
180+
} else {
181+
return type === 'string';
182+
}
183+
},
184+
_isSchemaObject: function(type) {
185+
return type === 'object';
186+
},
187+
_isSchemaArray: function(type) {
188+
return type === 'array';
189+
},
190+
/**
191+
* This is a fallback method.
192+
*/
193+
_schemaPropertyChanged: function(event, detail) {
194+
console.log('_schemaPropertyChanged(' + event + ',' + detail + ')');
195+
},
196+
/**
197+
* Debug method only useful for output of strange elements
198+
*/
199+
safeJSONString: function(obj, indent) {
200+
var censor = function censor(censor) {
201+
var i = 0;
202+
var seenValues = [];
203+
return function(key, value) {
204+
if (seenValues.indexOf(value) >= 0) {
205+
return '[Circular]';
206+
}
207+
seenValues.push(value);
208+
// if (i >= 29) // seems to be a harded maximum of 30 serialized objects?
209+
// return '[Unknown]';
210+
++i; // so we know we aren't using the original object anymore
211+
return value;
212+
}
213+
};
214+
return JSON.stringify(obj, censor(obj), indent);
215+
}
216+
};
217+
</script>

0 commit comments

Comments
 (0)