diff --git a/dist/js/brutusin-json-forms.js b/dist/js/brutusin-json-forms.js index dbc27d0..fe8d078 100644 --- a/dist/js/brutusin-json-forms.js +++ b/dist/js/brutusin-json-forms.js @@ -134,7 +134,9 @@ if (typeof brutusin === "undefined") { var error; var initialValue; var inputCounter = 0; + var root = schema; var formId = "BrutusinForms#" + BrutusinForms.instances.length; + populateSchemaMap("$", schema); validateDepencyMapIsAcyclic(); @@ -154,6 +156,8 @@ if (typeof brutusin === "undefined") { }; renderers["string"] = function (container, id, parentObject, propertyProvider, value) { + /// TODO change the handler for when there is a 'media' + /// specifier so it becomes a file element. var schemaId = getSchemaId(id); var s = getSchema(schemaId); var input; @@ -161,7 +165,14 @@ if (typeof brutusin === "undefined") { input = document.createElement("textarea"); if (value) { input.value = JSON.stringify(value, null, 4); + if (s.readOnly) + input.disabled = true; } + } else if (s.media) { + input = document.createElement("input"); + input.type = "file"; + appendChild(input, option, s); + // XXX TODO, encode the SOB properly. } else if (s.enum) { input = document.createElement("select"); if (!s.required) { @@ -183,9 +194,14 @@ if (typeof brutusin === "undefined") { if (!s.required) { selectedIndex++; } + if (s.readOnly) + input.disabled = true; } } - input.selectedIndex = selectedIndex; + if (s.enum.length === 1) + input.selectedIndex = 1; + else + input.selectedIndex = selectedIndex; } else { input = document.createElement("input"); if (s.type === "integer" || s.type === "number") { @@ -204,7 +220,11 @@ if (typeof brutusin === "undefined") { input.type = "text"; } if (value !== null && typeof value !== "undefined") { + // readOnly? input.value = value; + if (s.readOnly) + input.disabled = true; + } } input.schema = schemaId; @@ -320,7 +340,7 @@ if (typeof brutusin === "undefined") { input.onchange(); appendChild(container, input, s); }; - + renderers["oneOf"] = function (container, id, parentObject, propertyProvider, value) { var schemaId = getSchemaId(id); var s = getSchema(schemaId); @@ -334,20 +354,35 @@ if (typeof brutusin === "undefined") { appendChild(input, noption, s); for (var i = 0; i < s.oneOf.length; i++) { var option = document.createElement("option"); - var propId = id + "." + i; + var propId = schemaId + "." + i; var ss = getSchema(propId); var textNode = document.createTextNode(ss.title); option.value = s.oneOf[i]; appendChild(option, textNode, s); appendChild(input, option, s); + if (value === undefined) + continue; + if (s.readOnly) + input.disabled = true; + if (value.hasOwnProperty("type")) { + if (ss.hasOwnProperty("properties")) { + if (ss.properties.hasOwnProperty("type")) { + var tryit = getSchema(ss.properties.type); + if (value.type === tryit.enum[0]) { + input.selectedIndex = i + 1; + render(null, display, id + "." + (input.selectedIndex - 1), parentObject, propertyProvider, value); + } + } + } + } } input.onchange = function () { render(null, display, id + "." + (input.selectedIndex - 1), parentObject, propertyProvider, value); }; appendChild(container, input, s); appendChild(container, display, s); + }; - renderers["object"] = function (container, id, parentObject, propertyProvider, value) { function createStaticPropertyProvider(propname) { @@ -360,8 +395,13 @@ if (typeof brutusin === "undefined") { return ret; } - function addAdditionalProperty(current, table, id, name, value) { - var schemaId = getSchemaId(id); + function addAdditionalProperty(current, table, id, name, value, button) { + var schemaId; + if (button !== undefined) { + schemaId = getSchemaId(button.id); + } else { + schemaId = getSchemaId(id); + } var s = getSchema(schemaId); var tbody = table.tBodies[0]; var tr = document.createElement("tr"); @@ -431,18 +471,27 @@ if (typeof brutusin === "undefined") { nameInput.value = null; pp.onchange(nameInput.previousValue); }; - appendChild(innerTd1, nameInput, s); appendChild(innerTd2, removeButton, s); appendChild(innerTr, innerTd1, s); appendChild(innerTr, innerTd2, s); appendChild(innerTab, innerTr, s); appendChild(td1, innerTab, s); + if (button !== undefined) { + var secondTr = document.createElement("tr"); + var secondTd = document.createElement("td"); + appendChild(secondTd, document.createTextNode(button.pnp_pattern), s); + appendChild(secondTr, secondTd, s); + appendChild(innerTab, secondTr, s); + } appendChild(tr, td1, s); appendChild(tr, td2, s); appendChild(tbody, tr, s); appendChild(table, tbody, s); - render(null, td2, id, current, pp, value); + if (button !== undefined) + render(null, td2, button.id, current, pp, value); + else + render(null, td2, id, current, pp, value); if (name) { nameInput.value = name; nameInput.onblur(); @@ -484,36 +533,87 @@ if (typeof brutusin === "undefined") { render(td1, td2, propId, current, pp, propInitialValue); } } - if (s.additionalProperties) { - var addPropS = getSchema(s.additionalProperties); + var usedProps = []; + if (s.patternProperties || s.additionalProperties) { var div = document.createElement("div"); appendChild(div, table, s); - var addButton = document.createElement("button"); - addButton.setAttribute('type', 'button'); - addButton.onclick = function () { - addAdditionalProperty(current, table, id + "[*]"); - }; - if (s.maxProperties || s.minProperties) { - addButton.getValidationError = function () { - if (s.minProperties && propNum + table.rows.length < s.minProperties) { - return BrutusinForms.messages["minProperties"].format(s.minProperties); + if (s.patternProperties) { + for (var pattern in s.patternProperties) { + var patProps = s.patternProperties[pattern]; + var patdiv = document.createElement("div"); + var addButton = document.createElement("button"); + addButton.setAttribute('type', 'button'); + addButton.pnp_pattern = pattern.substr(0); + addButton.id = id + "[" + pattern + "]"; + addButton.onclick = function () { + addAdditionalProperty(current, table, id + "[" + pattern + "]", undefined, undefined, this); + }; + if (s.maxProperties || s.minProperties) { + addButton.getValidationError = function () { + if (s.minProperties && propNum + table.rows.length < s.minProperties) { + return BrutusinForms.messages["minProperties"].format(s.minProperties); + } + if (s.maxProperties && propNum + table.rows.length > s.maxProperties) { + return BrutusinForms.messages["maxProperties"].format(s.maxProperties); + } + }; } - if (s.maxProperties && propNum + table.rows.length > s.maxProperties) { - return BrutusinForms.messages["maxProperties"].format(s.maxProperties); + if (patProps.description) { + addButton.title = patProps.description; } - }; - } - if (addPropS.description) { - addButton.title = addPropS.description; + appendChild(addButton, document.createTextNode("Add " + pattern), s); + appendChild(patdiv, addButton, s); + if (value) { + for (var p in value) { + if (s.properties.hasOwnProperty(p)) { + continue; + } + var r = RegExp(pattern); + if (p.search(r) === -1) { + continue; + } + if (usedProps.indexOf(p) !== -1) { + continue; + } + addAdditionalProperty(current, table, id + "[" + pattern + "]", p, value[p]); + usedProps.push(p); + } + } + appendChild(div, patdiv, s); + } } - appendChild(addButton, document.createTextNode("Add"), s); - appendChild(div, addButton, s); - if (value) { - for (var p in value) { - if (s.properties.hasOwnProperty(p)) { - continue; + if (s.additionalProperties) { + var addPropS = getSchema(s.additionalProperties); + var addButton = document.createElement("button"); + addButton.setAttribute('type', 'button'); + addButton.onclick = function () { + addAdditionalProperty(current, table, id + "[*]", undefined); + }; + if (s.maxProperties || s.minProperties) { + addButton.getValidationError = function () { + if (s.minProperties && propNum + table.rows.length < s.minProperties) { + return BrutusinForms.messages["minProperties"].format(s.minProperties); + } + if (s.maxProperties && propNum + table.rows.length > s.maxProperties) { + return BrutusinForms.messages["maxProperties"].format(s.maxProperties); + } + }; + } + if (addPropS.description) { + addButton.title = addPropS.description; + } + appendChild(addButton, document.createTextNode("Add"), s); + appendChild(div, addButton, s); + if (value) { + for (var p in value) { + if (s.properties.hasOwnProperty(p)) { + continue; + } + if (usedProps.indexOf(p) !== -1) { + continue; + } + addAdditionalProperty(current, table, id + "[\"" + prop + "\"]", p, value[p], undefined); } - addAdditionalProperty(current, table, id + "[\"" + prop + "\"]", p, value[p]); } } appendChild(container, div, s); @@ -523,7 +623,7 @@ if (typeof brutusin === "undefined") { }; // end of object renderer renderers["array"] = function (container, id, parentObject, propertyProvider, value) { - function addItem(current, table, id, value) { + function addItem(current, table, id, value, readOnly) { var schemaId = getSchemaId(id); var s = getSchema(schemaId); var tbody = document.createElement("tbody"); @@ -538,6 +638,8 @@ if (typeof brutusin === "undefined") { var removeButton = document.createElement("button"); removeButton.setAttribute('type', 'button'); removeButton.className = "remove"; + if (readOnly === true) + removeButton.disabled = true; appendChild(removeButton, document.createTextNode("x"), s); var computRowCount = function () { for (var i = 0; i < table.rows.length; i++) { @@ -587,6 +689,8 @@ if (typeof brutusin === "undefined") { appendChild(div, table, s); appendChild(container, div, s); var addButton = document.createElement("button"); + if (s.readOnly) + addButton.disabled = true; addButton.setAttribute('type', 'button'); addButton.getValidationError = function () { if (s.minItems && s.minItems > table.rows.length) { @@ -607,7 +711,7 @@ if (typeof brutusin === "undefined") { appendChild(div, addButton, s); if (value && value instanceof Array) { for (var i = 0; i < value.length; i++) { - addItem(current, table, id + "[" + i + "]", value[i]); + addItem(current, table, id + "[" + i + "]", value[i], s.readOnly); } } appendChild(container, div, s); @@ -749,11 +853,36 @@ if (typeof brutusin === "undefined") { } return pseudoSchema; } + function getDefinition(path) { + var parts = path.split('/'); + var def = root; + for (var p in parts) { + if (p === 0) + continue; + def = def[parts[p]]; + + } + return def; + } function populateSchemaMap(name, schema) { var pseudoSchema = createPseudoSchema(schema); schemaMap[name] = pseudoSchema; - if (schema.type === "object") { + + if (schema.hasOwnProperty("oneOf")) { + pseudoSchema.oneOf = new Array(); + pseudoSchema.type = "oneOf"; + for (var i in schema.oneOf) { + var childProp = name + "." + i; + pseudoSchema.oneOf[i] = childProp; + populateSchemaMap(childProp, schema.oneOf[i]); + } + } else if (schema.hasOwnProperty("$ref")) { + var newSchema = getDefinition(schema["$ref"]); + //console.log("$REF",name,newSchema); + populateSchemaMap(name, newSchema); + + } else if (schema.type === "object") { if (schema.properties) { pseudoSchema.properties = new Object(); for (var prop in schema.properties) { @@ -762,10 +891,26 @@ if (typeof brutusin === "undefined") { populateSchemaMap(childProp, schema.properties[prop]); } } + if (schema.patternProperties) { + pseudoSchema.patternProperties = new Object(); + for (var pat in schema.patternProperties) { + var patChildProp = name + "[" + pat + "]"; + pseudoSchema.patternProperties[pat] = patChildProp; + var s = schema.patternProperties[pat]; + + if (s.hasOwnProperty("type") || s.hasOwnProperty("$ref") || + s.hasOwnProperty("oneOf")) { + populateSchemaMap(patChildProp, schema.patternProperties[pat]); + } else { + populateSchemaMap(patChildProp, SCHEMA_ANY); + } + } + } if (schema.additionalProperties) { var childProp = name + "[*]"; pseudoSchema.additionalProperties = childProp; - if (schema.additionalProperties.hasOwnProperty("type")) { + if (schema.additionalProperties.hasOwnProperty("type") || + schema.additionalProperties.hasOwnProperty("oneOf")) { populateSchemaMap(childProp, schema.additionalProperties); } else { populateSchemaMap(childProp, SCHEMA_ANY); @@ -774,15 +919,6 @@ if (typeof brutusin === "undefined") { } else if (schema.type === "array") { pseudoSchema.items = name + "[#]"; populateSchemaMap(pseudoSchema.items, schema.items); - } else if (schema.hasOwnProperty("oneOf")) { - pseudoSchema.oneOf = new Array(); - pseudoSchema.type = "oneOf"; - for (var i in schema.oneOf) { - // console.log(schema.oneOf[i]); - var childProp = name + "." + i; - pseudoSchema.oneOf[i] = childProp; - populateSchemaMap(childProp, schema.oneOf[i]); - } } if (schema.hasOwnProperty("dependsOn")) { if (schema.dependsOn === null) { @@ -882,7 +1018,7 @@ if (typeof brutusin === "undefined") { renderInfoMap[schemaId].value = value; clear(titleContainer); clear(container); - // console.log(s.type, id, s); + //console.log(id,s,value); var r = renderers[s.type]; if (r && !s.dependsOn) { if (s.title) { @@ -1183,6 +1319,6 @@ if (typeof brutusin === "undefined") { return ret; } } - } + }; brutusin["json-forms"] = BrutusinForms; }()); diff --git a/dist/js/brutusin-json-forms.min.js b/dist/js/brutusin-json-forms.min.js index a62f2be..bf85700 100644 --- a/dist/js/brutusin-json-forms.min.js +++ b/dist/js/brutusin-json-forms.min.js @@ -1 +1 @@ -if("undefined"==typeof brutusin)window.brutusin=new Object;else if("object"!=typeof brutusin)throw"brutusin global variable already exists";!function(){String.prototype.startsWith||(String.prototype.startsWith=function(e,t){return t=t||0,this.indexOf(e,t)===t}),String.prototype.endsWith||(String.prototype.endsWith=function(e,t){var n=this.toString();(void 0===t||t>n.length)&&(t=n.length),t-=e.length;var r=n.indexOf(e,t);return-1!==r&&r===t}),String.prototype.includes||(String.prototype.includes=function(){"use strict";return-1!==String.prototype.indexOf.apply(this,arguments)}),String.prototype.format||(String.prototype.format=function(){for(var e=this,t=0;t0)throw"Error parsing expression '"+e+"': Multiple tokens found inside a bracket";o+=s,i++}else n[n.length]=s;if(u===r.length-1&&a)throw"Error parsing expression '"+e+"': Unbalanced [ found"}this.exp=e,this.queue=n,this.visit=function(e,t){function n(e,r,a,i,o){if(null!=a){var u=r.shift();if("$"===u){e="$";var u=r.shift()}if(u)if(Array.isArray(a)){if(!u.startsWith("["))throw"Node '"+e+"' is of type array";var s=u.substring(1,u.length-1);if(s.equals("#"))for(var l=0;lc)throw"Element '"+s+"' of node '"+e+"' is lower than zero";var d=a[c];n(e+u,r.slice(0),d,a,c)}}else{if("object"!=typeof a)throw"boolean"==typeof a||"number"==typeof a||"string"==typeof a?"Node is leaf but still are tokens remaining: "+u:"Node type '"+typeof a+"' not supported for index field '"+e+"'";if("[*]"===u)for(var m in a){var d=a[m];n(e+u,r.slice(0),d,a,m),n(e+'["'+m+'"]',r.slice(0),d,a,m)}else{var d;if(u.startsWith("[")){var s=u.substring(1,u.length-1);if(!s.startsWith('"')&&!s.startsWith("'"))throw"Element '"+s+"' of node '"+e+"' must be a string expression or wilcard '*'";s=s.substring(1,s.length()-1),e+=u,d=a[s]}else e=e.length>0?e+"."+u:u,d=a[u];n(e,r,d,a,u)}}else t(a,i,o)}}n(this.exp,this.queue,e)}}var SCHEMA_ANY={type:"any"},obj=new Object,schemaMap=new Object,dependencyMap=new Object,renderInfoMap=new Object,container,data,error,initialValue,inputCounter=0,formId="BrutusinForms#"+BrutusinForms.instances.length;populateSchemaMap("$",schema),validateDepencyMapIsAcyclic();var renderers=new Object;return renderers.integer=function(e,t,n,r,a){renderers.string(e,t,n,r,a)},renderers.number=function(e,t,n,r,a){renderers.string(e,t,n,r,a)},renderers.any=function(e,t,n,r,a){renderers.string(e,t,n,r,a)},renderers.string=function(e,t,n,r,a){var i,o=getSchemaId(t),u=getSchema(o);if("any"===u.type)i=document.createElement("textarea"),a&&(i.value=JSON.stringify(a,null,4));else if(u["enum"]){if(i=document.createElement("select"),!u.required){var s=document.createElement("option"),l=document.createTextNode("");s.value="",appendChild(s,l,u),appendChild(i,s,u)}for(var d=0,c=0;ce.length))return BrutusinForms.messages.minLength.format(u.minLength);if(u.maxLength&&e&&u.maxLength=u.maximum)return BrutusinForms.messages.exclusiveMaximum.format(u.maximum);if(!u.exclusiveMaximum&&e>u.maximum)return BrutusinForms.messages.maximum.format(u.maximum)}if(u.hasOwnProperty("minimum")){if(u.exclusiveMinimum&&e<=u.minimum)return BrutusinForms.messages.exclusiveMinimum.format(u.minimum);if(!u.exclusiveMinimum&&es.maxProperties?BrutusinForms.messages.maxProperties.format(s.maxProperties):void 0}),x.description&&(C.title=x.description),appendChild(C,document.createTextNode("Add"),s),appendChild(w,C,s),a)for(var O in a)s.properties.hasOwnProperty(O)||o(l,d,t+'["'+p+'"]',O,a[O]);appendChild(e,w,s)}else appendChild(e,d,s)},renderers.array=function(e,t,n,r,a){function i(e,t,n,r){var a=getSchemaId(n),i=getSchema(a),o=document.createElement("tbody"),u=document.createElement("tr");u.className="item";var s=document.createElement("td");s.className="item-index";var l=document.createElement("td");l.className="item-action";var d=document.createElement("td");d.className="item-value";var c=document.createElement("button");c.setAttribute("type","button"),c.className="remove",appendChild(c,document.createTextNode("x"),i);var m=function(){for(var e=0;ec.rows.length?BrutusinForms.messages.minItems.format(u.minItems):u.maxItems&&u.maxItemsr.length)&&(t=r.length),t-=e.length;var n=r.indexOf(e,t);return-1!==n&&n===t}),String.prototype.includes||(String.prototype.includes=function(){"use strict";return-1!==String.prototype.indexOf.apply(this,arguments)}),String.prototype.format||(String.prototype.format=function(){for(var e=this,t=0;t0)throw"Error parsing expression '"+e+"': Multiple tokens found inside a bracket";o+=u,i++}else r[r.length]=u;if(s===n.length-1&&a)throw"Error parsing expression '"+e+"': Unbalanced [ found"}this.exp=e,this.queue=r,this.visit=function(e,t){function r(e,n,a,i,o){if(null!=a){var s=n.shift();if("$"===s){e="$";var s=n.shift()}if(s)if(Array.isArray(a)){if(!s.startsWith("["))throw"Node '"+e+"' is of type array";var u=s.substring(1,s.length-1);if(u.equals("#"))for(var l=0;lp)throw"Element '"+u+"' of node '"+e+"' is lower than zero";var d=a[p];r(e+s,n.slice(0),d,a,p)}}else{if("object"!=typeof a)throw"boolean"==typeof a||"number"==typeof a||"string"==typeof a?"Node is leaf but still are tokens remaining: "+s:"Node type '"+typeof a+"' not supported for index field '"+e+"'";if("[*]"===s)for(var c in a){var d=a[c];r(e+s,n.slice(0),d,a,c),r(e+'["'+c+'"]',n.slice(0),d,a,c)}else{var d;if(s.startsWith("[")){var u=s.substring(1,s.length-1);if(!u.startsWith('"')&&!u.startsWith("'"))throw"Element '"+u+"' of node '"+e+"' must be a string expression or wilcard '*'";u=u.substring(1,u.length()-1),e+=s,d=a[u]}else e=e.length>0?e+"."+s:s,d=a[s];r(e,n,d,a,s)}}else t(a,i,o)}}r(this.exp,this.queue,e)}}var SCHEMA_ANY={type:"any"},obj=new Object,schemaMap=new Object,dependencyMap=new Object,renderInfoMap=new Object,container,data,error,initialValue,inputCounter=0,root=schema,formId="BrutusinForms#"+BrutusinForms.instances.length;populateSchemaMap("$",schema),validateDepencyMapIsAcyclic();var renderers=new Object;return renderers.integer=function(e,t,r,n,a){renderers.string(e,t,r,n,a)},renderers.number=function(e,t,r,n,a){renderers.string(e,t,r,n,a)},renderers.any=function(e,t,r,n,a){renderers.string(e,t,r,n,a)},renderers.string=function(e,t,r,n,a){var i,o=getSchemaId(t),s=getSchema(o);if("any"===s.type)i=document.createElement("textarea"),a&&(i.value=JSON.stringify(a,null,4),s.readOnly&&(i.disabled=!0));else if(s.media)i=document.createElement("input"),i.type="file",appendChild(i,u,s);else if(s["enum"]){if(i=document.createElement("select"),!s.required){var u=document.createElement("option"),l=document.createTextNode("");u.value="",appendChild(u,l,s),appendChild(i,u,s)}for(var d=0,p=0;pe.length))return BrutusinForms.messages.minLength.format(s.minLength);if(s.maxLength&&e&&s.maxLength=s.maximum)return BrutusinForms.messages.exclusiveMaximum.format(s.maximum);if(!s.exclusiveMaximum&&e>s.maximum)return BrutusinForms.messages.maximum.format(s.maximum)}if(s.hasOwnProperty("minimum")){if(s.exclusiveMinimum&&e<=s.minimum)return BrutusinForms.messages.exclusiveMinimum.format(s.minimum);if(!s.exclusiveMinimum&&eu.maxProperties?BrutusinForms.messages.maxProperties.format(u.maxProperties):void 0}),C.description&&(E.title=C.description),appendChild(E,document.createTextNode("Add "+O),u),appendChild(P,E,u),a)for(var S in a)if(!u.properties.hasOwnProperty(S)){var V=RegExp(O);-1!==S.search(V)&&-1===x.indexOf(S)&&(o(l,d,t+"["+O+"]",S,a[S]),x.push(S))}appendChild(w,P,u)}if(u.additionalProperties){var I=getSchema(u.additionalProperties),E=document.createElement("button");if(E.setAttribute("type","button"),E.onclick=function(){o(l,d,t+"[*]",void 0)},(u.maxProperties||u.minProperties)&&(E.getValidationError=function(){return u.minProperties&&c+d.rows.lengthu.maxProperties?BrutusinForms.messages.maxProperties.format(u.maxProperties):void 0}),I.description&&(E.title=I.description),appendChild(E,document.createTextNode("Add"),u),appendChild(w,E,u),a)for(var S in a)u.properties.hasOwnProperty(S)||-1===x.indexOf(S)&&o(l,d,t+'["'+m+'"]',S,a[S],void 0)}appendChild(e,w,u)}else appendChild(e,d,u)},renderers.array=function(e,t,r,n,a){function i(e,t,r,n,a){var i=getSchemaId(r),o=getSchema(i),s=document.createElement("tbody"),u=document.createElement("tr");u.className="item";var l=document.createElement("td");l.className="item-index";var d=document.createElement("td");d.className="item-action";var p=document.createElement("td");p.className="item-value";var c=document.createElement("button");c.setAttribute("type","button"),c.className="remove",a===!0&&(c.disabled=!0),appendChild(c,document.createTextNode("x"),o);var m=function(){for(var e=0;ep.rows.length?BrutusinForms.messages.minItems.format(s.minItems):s.maxItems&&s.maxItems