From 328b1e4d573eb92afddea794695ff07d9c06f50a Mon Sep 17 00:00:00 2001 From: robb Date: Mon, 15 Jan 2018 10:19:03 +0800 Subject: [PATCH 1/7] schema.enum enhancement for issue #85 --- src/js/brutusin-json-forms.js | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/js/brutusin-json-forms.js b/src/js/brutusin-json-forms.js index 49ee5ea..67c5b8c 100644 --- a/src/js/brutusin-json-forms.js +++ b/src/js/brutusin-json-forms.js @@ -190,11 +190,25 @@ if (typeof brutusin === "undefined") { var selectedIndex = 0; for (var i = 0; i < s.enum.length; i++) { var option = document.createElement("option"); - var textNode = document.createTextNode(s.enum[i]); - option.value = s.enum[i]; + + var optionText = undefined; + var optionValue = undefined; + if( typeof s.enum[i] === 'object'){ + optionText = s.enum[i]['text']; + optionValue = s.enum[i]['value']; + } + optionText = optionText !== undefined ? optionText : s.enum[i]; + optionValue = optionValue !== undefined ? optionValue : optionText; + + // var textNode = document.createTextNode(s.enum[i]); + // option.value = s.enum[i]; + var textNode = document.createTextNode(optionText); + option.value = optionValue; + appendChild(option, textNode, s); appendChild(input, option, s); - if (value && s.enum[i] === value) { + // if (value && s.enum[i] === value) { + if (value && optionValue === value) { selectedIndex = i; if (!s.required) { selectedIndex++; From faba40107a7bee737b3545a1d37050e80b8f5224 Mon Sep 17 00:00:00 2001 From: robb Date: Wed, 17 Jan 2018 19:51:52 +0800 Subject: [PATCH 2/7] appendedProperties feature --- src/js/brutusin-json-forms.js | 153 ++++++++++++++++++++++++++++++---- 1 file changed, 137 insertions(+), 16 deletions(-) diff --git a/src/js/brutusin-json-forms.js b/src/js/brutusin-json-forms.js index 67c5b8c..a9e4bfd 100644 --- a/src/js/brutusin-json-forms.js +++ b/src/js/brutusin-json-forms.js @@ -132,6 +132,7 @@ if (typeof brutusin === "undefined") { var schemaMap = new Object(); var dependencyMap = new Object(); var renderInfoMap = new Object(); + var appendedPropertiesDependencies = []; var container; var data; var error; @@ -317,18 +318,20 @@ if (typeof brutusin === "undefined") { }; input.onchange = function () { - var value; + var value, old; try { value = getValue(s, input); } catch (error) { value = null; } if (parentObject) { + old = parentObject[propertyProvider.getValue()]; parentObject[propertyProvider.getValue()] = value; } else { data = value; } onDependencyChanged(schemaId, input); + renderAppendedProperties(schemaId, old, value); }; if (s.description) { @@ -453,17 +456,7 @@ if (typeof brutusin === "undefined") { }; renderers["object"] = function (container, id, parentObject, propertyProvider, value) { - - function createStaticPropertyProvider(propname) { - var ret = new Object(); - ret.getValue = function () { - return propname; - }; - ret.onchange = function (oldName) { - }; - return ret; - } - + function addAdditionalProperty(current, table, id, name, value, pattern) { var schemaId = getSchemaId(id); var s = getSchema(schemaId); @@ -1076,6 +1069,7 @@ if (typeof brutusin === "undefined") { populateSchemaMap(childProp, subSchema); } } + if (schema.patternProperties) { pseudoSchema.patternProperties = new Object(); for (var pat in schema.patternProperties) { @@ -1091,6 +1085,7 @@ if (typeof brutusin === "undefined") { } } } + if (schema.additionalProperties) { var childProp = name + "[*]"; pseudoSchema.additionalProperties = childProp; @@ -1101,6 +1096,25 @@ if (typeof brutusin === "undefined") { populateSchemaMap(childProp, SCHEMA_ANY); } } + + if (schema.appendedProperties && schema.appendedProperties.hasOwnProperty("dependsOn") && schema.appendedProperties.hasOwnProperty("appendix")) { + pseudoSchema.appendedProperties = new Object(); + var dependsOnProp = schema.appendedProperties.dependsOn; + var appendix = schema.appendedProperties.appendix; + + if(appendedPropertiesDependencies.indexOf(name + '.' + dependsOnProp) === -1){ + appendedPropertiesDependencies.push(name + '.' + dependsOnProp); + } + + for (var option in appendix) { + var optionSchemaId = name + "{" + dependsOnProp + "}" + "[" + option + "]"; + pseudoSchema.appendedProperties[option] = optionSchemaId; + populateSchemaMap(optionSchemaId, appendix[option]); + for (var appendedProp in appendix[option]) { + populateSchemaMap(optionSchemaId + "." + appendedProp, appendix[option][appendedProp]); + } + } + } } else if (schema.type === "array") { pseudoSchema.items = name + "[#]"; populateSchemaMap(pseudoSchema.items, schema.items); @@ -1338,11 +1352,10 @@ if (typeof brutusin === "undefined") { } function onDependencyChanged(name, source) { - var arr = dependencyMap[name]; if (!arr || !obj.schemaResolver) { return; - } + } var cb = function (schemas) { if (schemas) { for (var id in schemas) { @@ -1361,8 +1374,6 @@ if (typeof brutusin === "undefined") { }; BrutusinForms.onResolutionStarted(source); obj.schemaResolver(arr, obj.getData(), cb); - - } function Expression(exp) { @@ -1420,6 +1431,18 @@ if (typeof brutusin === "undefined") { name = "$"; var currentToken = queue.shift(); } + + // processing appendedProperties schemaId + if( /^\$\{(.+)\}$/.test(currentToken) ) { + var optionToken = queue.shift(); + if( !/^\[(.+)\]$/.test(optionToken) ) { + queue.splice(0,0,optionToken); + } else { + name = currentToken + optionToken; + currentToken = queue.shift(); + } + } + if (!currentToken) { visitor(data, parentData, property); } else if (Array.isArray(data)) { @@ -1540,6 +1563,104 @@ if (typeof brutusin === "undefined") { return ret; } } + + function createStaticPropertyProvider(propname) { + var ret = new Object(); + ret.getValue = function () { + return propname; + }; + ret.onchange = function (oldName) { + }; + return ret; + } + + function appendProperty(current, tbody, id, name, value){ + var propId = getSchemaId(id); + var propSchema = getSchema(propId); + if( !propSchema ) + return; + + var tr = document.createElement("tr"); + var td1 = document.createElement("td"); + td1.className = "prop-name"; + var td2 = document.createElement("td"); + td2.className = "prop-value"; + + appendChild(tbody, tr, propSchema); + appendChild(tr, td1, propSchema); + appendChild(tr, td2, propSchema); + render(td1, td2, propId, current, createStaticPropertyProvider(name), value); + } + + function renderAppendedProperties(schemaId, oldValue, newValue){ + var schemaIdRegex = /^(.+)\.(.+)$/; + var matches = schemaIdRegex.exec(schemaId); + if( !matches ) { + return; + } + + var parentSchemaId = matches[1]; + var dependsOnProp = matches[2]; + + var appendedPropPrefix = parentSchemaId + "{" + dependsOnProp + "}" + var parentSchema = getSchema(parentSchemaId); + if(!parentSchema || !parentSchema.appendedProperties) { + return; + } + var isAppendedDependency = false; + for(var key in parentSchema.appendedProperties) { + if(parentSchema.appendedProperties[key].startsWith(appendedPropPrefix)){ + isAppendedDependency = true; + break; + } + } + if(!isAppendedDependency){ + return; + } + + var oldAppendedPropSchemaId = parentSchema.appendedProperties[oldValue]; + var newAppendedPropSchemaId = parentSchema.appendedProperties[newValue]; + if( !oldAppendedPropSchemaId && !newAppendedPropSchemaId ) { + return; + } + + try { + var tbody = renderInfoMap[schemaId].container.parentElement.parentElement; + var current = renderInfoMap[schemaId].parentObject; + } catch (err) { + return; + } + + // Clear old appended properties + if( oldAppendedPropSchemaId !== undefined ) { + for(var renderInfoKey in renderInfoMap) { + if( renderInfoKey.startsWith(oldAppendedPropSchemaId) ) { + var renderInfo = renderInfoMap[renderInfoKey]; + if(renderInfo){ + var tr = renderInfo.container.parentElement; + tbody.removeChild(tr); + delete renderInfoMap[renderInfoKey]; + cleanData(renderInfoKey); + } + } + } + } + + // Render new appended properties + if( newAppendedPropSchemaId !== undefined ) { + var rendered = []; + var value = tbody.getRootNode() === document ? data : initialValue; + + for( var p in schemaMap[newAppendedPropSchemaId] ) { + if( ( parentSchema.properties && parentSchema.properties.hasOwnProperty(p) ) || rendered.indexOf(p) >= 0){ + continue; + } + + appendProperty(value, tbody, newAppendedPropSchemaId + "." + p , p, value[p]); + rendered.push(p); + } + } + } }; brutusin["json-forms"] = BrutusinForms; }()); From 8c5735d16bb02db3a7561399abee825af7414241 Mon Sep 17 00:00:00 2001 From: robb Date: Thu, 18 Jan 2018 09:44:09 +0800 Subject: [PATCH 3/7] fix bug --- src/js/brutusin-json-forms.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/js/brutusin-json-forms.js b/src/js/brutusin-json-forms.js index a9e4bfd..8c0b3c2 100644 --- a/src/js/brutusin-json-forms.js +++ b/src/js/brutusin-json-forms.js @@ -1649,8 +1649,11 @@ if (typeof brutusin === "undefined") { // Render new appended properties if( newAppendedPropSchemaId !== undefined ) { var rendered = []; - var value = tbody.getRootNode() === document ? data : initialValue; - + var value = tbody.getRootNode() !== document && initialValue ? initialValue : data; + if( !value ){ + value = {}; + value[dependsOnProp] = newValue; + } for( var p in schemaMap[newAppendedPropSchemaId] ) { if( ( parentSchema.properties && parentSchema.properties.hasOwnProperty(p) ) || rendered.indexOf(p) >= 0){ continue; From 088dc56478400cbb79108cf8f9503c92999f3f56 Mon Sep 17 00:00:00 2001 From: robb Date: Thu, 18 Jan 2018 10:22:37 +0800 Subject: [PATCH 4/7] fix bug --- src/js/brutusin-json-forms.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/js/brutusin-json-forms.js b/src/js/brutusin-json-forms.js index 8c0b3c2..293d32b 100644 --- a/src/js/brutusin-json-forms.js +++ b/src/js/brutusin-json-forms.js @@ -1654,12 +1654,13 @@ if (typeof brutusin === "undefined") { value = {}; value[dependsOnProp] = newValue; } + // data = value; for( var p in schemaMap[newAppendedPropSchemaId] ) { if( ( parentSchema.properties && parentSchema.properties.hasOwnProperty(p) ) || rendered.indexOf(p) >= 0){ continue; } - appendProperty(value, tbody, newAppendedPropSchemaId + "." + p , p, value[p]); + appendProperty(data, tbody, newAppendedPropSchemaId + "." + p , p, value[p]); rendered.push(p); } } From da51438a08a6f43e481f96b02ba2e891d341e7a9 Mon Sep 17 00:00:00 2001 From: robb Date: Thu, 18 Jan 2018 11:26:27 +0800 Subject: [PATCH 5/7] fix bug --- src/js/brutusin-json-forms.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/brutusin-json-forms.js b/src/js/brutusin-json-forms.js index 293d32b..ccbdb8d 100644 --- a/src/js/brutusin-json-forms.js +++ b/src/js/brutusin-json-forms.js @@ -1107,7 +1107,7 @@ if (typeof brutusin === "undefined") { } for (var option in appendix) { - var optionSchemaId = name + "{" + dependsOnProp + "}" + "[" + option + "]"; + var optionSchemaId = name + "{" + dependsOnProp + "}" + "[\'" + option + "\']"; pseudoSchema.appendedProperties[option] = optionSchemaId; populateSchemaMap(optionSchemaId, appendix[option]); for (var appendedProp in appendix[option]) { From 25593965b43ca41adf20b37bd47884e7923e3dcf Mon Sep 17 00:00:00 2001 From: robb Date: Thu, 18 Jan 2018 14:32:03 +0800 Subject: [PATCH 6/7] remove useless code --- src/js/brutusin-json-forms.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/js/brutusin-json-forms.js b/src/js/brutusin-json-forms.js index ccbdb8d..28ee93a 100644 --- a/src/js/brutusin-json-forms.js +++ b/src/js/brutusin-json-forms.js @@ -132,7 +132,6 @@ if (typeof brutusin === "undefined") { var schemaMap = new Object(); var dependencyMap = new Object(); var renderInfoMap = new Object(); - var appendedPropertiesDependencies = []; var container; var data; var error; @@ -1102,10 +1101,6 @@ if (typeof brutusin === "undefined") { var dependsOnProp = schema.appendedProperties.dependsOn; var appendix = schema.appendedProperties.appendix; - if(appendedPropertiesDependencies.indexOf(name + '.' + dependsOnProp) === -1){ - appendedPropertiesDependencies.push(name + '.' + dependsOnProp); - } - for (var option in appendix) { var optionSchemaId = name + "{" + dependsOnProp + "}" + "[\'" + option + "\']"; pseudoSchema.appendedProperties[option] = optionSchemaId; @@ -1650,10 +1645,12 @@ if (typeof brutusin === "undefined") { if( newAppendedPropSchemaId !== undefined ) { var rendered = []; var value = tbody.getRootNode() !== document && initialValue ? initialValue : data; + if( !value ){ value = {}; value[dependsOnProp] = newValue; } + // data = value; for( var p in schemaMap[newAppendedPropSchemaId] ) { if( ( parentSchema.properties && parentSchema.properties.hasOwnProperty(p) ) || rendered.indexOf(p) >= 0){ From cc1e3e929919c20fe577af788eb1fd0f05dc058a Mon Sep 17 00:00:00 2001 From: robb Date: Thu, 25 Jan 2018 15:20:58 +0800 Subject: [PATCH 7/7] Ignore file type value --- src/js/brutusin-json-forms.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/brutusin-json-forms.js b/src/js/brutusin-json-forms.js index 28ee93a..62e2877 100644 --- a/src/js/brutusin-json-forms.js +++ b/src/js/brutusin-json-forms.js @@ -854,7 +854,7 @@ if (typeof brutusin === "undefined") { return clone; } else if (object === "") { return null; - } else if (object instanceof Object) { + } else if (object instanceof Object && !(object instanceof File)) { var clone = new Object(); var nonEmpty = false; for (var prop in object) {