Merge pull request #285 from tdakanalis/feature/enumAsDropDownMenus

Display Enums As Drop Downs
This commit is contained in:
Jos de Jong 2016-04-11 20:15:01 +02:00
commit 953acd2055
1 changed files with 112 additions and 1 deletions

View File

@ -1262,12 +1262,64 @@ Node.prototype._updateDomValue = function () {
this.dom.checkbox.checked = this.value; this.dom.checkbox.checked = this.value;
} }
//If the node has an enum property and it is editable lets create the select element
else if (this.enum && this.editable.value) {
if (!this.dom.select) {
this.dom.select = document.createElement('select');
this.id = this.field + "_" + new Date().getUTCMilliseconds();
this.dom.select.id = this.id;
this.dom.select.name = this.dom.select.id;
//Create the default empty option
this.dom.select.option = document.createElement('option');
this.dom.select.option.value = '';
this.dom.select.option.innerHTML = '--';
this.dom.select.appendChild(this.dom.select.option);
//Iterate all enum values and add them as options
for(var i = 0; i < this.enum.enum.length; i++) {
this.dom.select.option = document.createElement('option');
this.dom.select.option.value = this.enum.enum[i];
this.dom.select.option.innerHTML = this.enum.enum[i];
if(this.dom.select.option.value == this.value){
this.dom.select.option.selected = true;
}
this.dom.select.appendChild(this.dom.select.option);
}
this.dom.tdSelect = document.createElement('td');
this.dom.tdSelect.className = 'jsoneditor-tree';
this.dom.tdSelect.appendChild(this.dom.select);
this.dom.tdValue.parentNode.insertBefore(this.dom.tdSelect, this.dom.tdValue);
//If the enum is inside a composite type display both the simple input and the dropdown field
if(this.schema !== undefined && (
!this.schema.hasOwnProperty("oneOf") &&
!this.schema.hasOwnProperty("anyOf") &&
!this.schema.hasOwnProperty("anyOf") &&
!this.schema.hasOwnProperty("allOf"))
) {
this.valueFieldHTML = this.dom.tdValue.innerHTML;
this.dom.tdValue.style.visibility = 'hidden';
this.dom.tdValue.innerHTML = '';
} else {
delete this.valueFieldHTML;
}
}
}
else { else {
// cleanup checkbox when displayed // cleanup checkbox when displayed
if (this.dom.tdCheckbox) { if (this.dom.tdCheckbox) {
this.dom.tdCheckbox.parentNode.removeChild(this.dom.tdCheckbox); this.dom.tdCheckbox.parentNode.removeChild(this.dom.tdCheckbox);
delete this.dom.tdCheckbox; delete this.dom.tdCheckbox;
delete this.dom.checkbox; delete this.dom.checkbox;
} else if (this.dom.tdSelect) {
this.dom.tdSelect.parentNode.removeChild(this.dom.tdSelect);
delete this.dom.tdSelect;
delete this.dom.select;
this.dom.tdValue.innerHTML = this.valueFieldHTML;
this.dom.tdValue.style.visibility = '';
delete this.valueFieldHTML;
} }
} }
@ -1879,6 +1931,34 @@ Node.prototype.updateDom = function (options) {
domField.innerHTML = this._escapeHTML(field); domField.innerHTML = this._escapeHTML(field);
} }
//Locating the schema of the node and checking for any enum type
if(this.editor && this.editor.options) {
//Search for the schema element of the current node and store it in the schema attribute.
//Hereafter, wherever you have access in the node you will have also access in its own schema.
this.schema = this._getJsonObject(this.editor.options.schema, 'name', field)[0];
if(!this.schema) {
this.schema = this._getJsonObject(this.editor.options.schema, field)[0];
}
//Search for any enumeration type in the schema of the current node.
//Enum types can be also be part of a composite type.
if(this.schema){
if(this.schema.hasOwnProperty('enum')){
this.enum = new Object();
this.enum.enum = this.schema.enum;
} else if(this.schema.hasOwnProperty('oneOf')){
this.enum = this._getJsonObject(this.schema.oneOf, 'enum')[0];
} else if(this.schema.hasOwnProperty('anyOf')){
this.enum = this._getJsonObject(this.schema.anyOf, 'enum')[0];
} else if(this.schema.hasOwnProperty('allOf')){
this.enum = this._getJsonObject(this.schema.allOf, 'enum')[0];
} else {
delete this.enum;
}
} else {
delete this.enum;
}
}
// apply value to DOM // apply value to DOM
var domValue = this.dom.value; var domValue = this.dom.value;
if (domValue) { if (domValue) {
@ -1922,6 +2002,31 @@ Node.prototype.updateDom = function (options) {
} }
}; };
/**
* Get all sub-elements of the given object with the specified key and value.
* @private
*/
Node.prototype._getJsonObject = function (obj, key, val) {
var objects = [];
for (var i in obj) {
if (!obj.hasOwnProperty(i)) continue;
if (typeof obj[i] == 'object') {
if(i === key && val === undefined){
if(Array.isArray(obj[i])) {
objects.push(obj);
} else {
objects.push(obj[i]);
}
} else {
objects = objects.concat(this._getJsonObject(obj[i], key, val));
}
} else if (i == key && obj[key] == val) {
objects.push(obj);
}
}
return objects;
};
/** /**
* Update the DOM of the childs of a node: update indexes and undefined field * Update the DOM of the childs of a node: update indexes and undefined field
* names. * names.
@ -2116,6 +2221,12 @@ Node.prototype.onEvent = function (event) {
this.dom.value.innerHTML = !this.value; this.dom.value.innerHTML = !this.value;
this._getDomValue(); this._getDomValue();
} }
//Update the value of the node based on the selected option
if (type == 'change' && target == dom.select) {
this.dom.value.innerHTML = dom.select.value;
this._getDomValue();
this._updateDomValue();
}
// value events // value events
var domValue = dom.value; var domValue = dom.value;
@ -2182,7 +2293,7 @@ Node.prototype.onEvent = function (event) {
case 'input': case 'input':
this._getDomField(true); this._getDomField(true);
this._updateDomField(); this.updateDom();
break; break;
case 'keydown': case 'keydown':