/**
* Extending JSONform with custom fields
* https://github.com/jsonform/jsonform/wiki
* @file jsonform.ext.js
* @sample
* {
// The template describes the HTML that the field will generate.
// It uses Underscore.js templates.
template: '<div><div id="<%=node.id%>"><%=value%></div></div>',
// Set the inputfield flag when the field is a real input field
// that produces a value. Set the array flag when it creates an
// array of fields. Both flags are mutually exclusive.
// Do not set any of these flags for containers and other types
// of fields.
inputfield: (true || false || undefined),
array: (true || false || undefined),
// Most real input fields should set this flag that wraps the
// generated content into the HTML code needed to report errors
fieldtemplate: (true || false),
// Return the root element created by the field
// (el is the DOM element whose id is node.id,
// this function is only useful when el is not the root
// element in the field's template)
getElement: function (el) {
// Adjust the following based on your template. In this example
// there is an additional <div> so we need to go one level up.
return $(el).parent().get(0);
},
// This is where you can complete the data that will be used
// to run the template string
onBeforeRender: function (data, node) {},
// This is where you can enhance the generated HTML by adding
// event handlers if needed
onInsert: function (evt, node) {}
};
*/
const JSONFormExt = {};
JSONFormExt.htmlentities = function(str){
var element = document.createElement('div');
element.textContent = str;
return element.innerHTML.replace(/"/g, '"').replace(/'/g, ''');
}
JSONFormExt.init = function() {
console.log("JSONFormExt.init loaded");
// JSONForm.fieldTypes['html'] = {
// template : '<div class="form-group"><div id="<%=node.id%>"><%=elt.content%></div></div>',
// inputfield :false,
// array:false,
// getElement: function (el) {
// // el is the place with node.id
// // Adjust the following based on your template. In this example
// // there is an additional <div> so we need to go one level up.
// return $(el).parent().get(0);
// },
// onBeforeRender: function (data, node) {},
// onInsert: function (evt, node) {}
// };
JSONForm.fieldTypes['html'] = {
template : '<div class="form-group"><%=elt.content || elt.value%></div>',
};
JSONForm.fieldTypes['hr'] = {
template : '<div class="form-group"><hr /></div>',
};
JSONForm.fieldTypes['info'] = {
template : `<div class="form-group blockBox infoBlock withIcon" ><%=elt.content || elt.value%></div>`,
};
JSONForm.fieldTypes['warn'] = {
template : `<div class="form-group blockBox attentionBlock withIcon" ><%=elt.content || elt.value%></div>`,
};
JSONForm.fieldTypes['error'] = {
template : `<div class="form-group blockBox errorBlock withIcon" ><%=elt.content || elt.value%></div>`,
};
JSONForm.fieldTypes['selectencoding'] = {...{}, ...JSONForm.fieldTypes.select};
JSONForm.fieldTypes['selectencoding'].onBeforeRender = function(data, node) {
node.options = [
"",
"utf8",
"utf16le",
"UTF-16",
"UTF-16BE",
"ascii",
"ISO-8859-1",
"ISO-8859-16",
"koi8-r",
"koi8-u",
"koi8-ru",
"koi8-t",
"Shift_JIS",
"Windows-31j",
"Windows932",
"EUC-JP",
"GB2312",
"GBK",
"GB18030",
"Windows936",
"EUC-CN",
"KS_C_5601",
"Windows949",
"EUC-KR",
"Big5",
"Big5-HKSCS",
"Windows950"
]
};
JSONForm.fieldTypes['combobox'] = {
"template": `<div><input type="search" class='form-control<%= (fieldHtmlClass ? " " + fieldHtmlClass : "") %>'name="<%= node.name %>" value="<%= escape(value) %>" id="<%= id %>" aria-label="<%= node.title ? escape(node.title) : node.name %>"<%= (node.disabled? " disabled" : "")%><%= (node.readOnly ? " readonly='readonly'" : "") %><%= (node.schemaElement && (node.schemaElement.step > 0 || node.schemaElement.step == "any") ? " step='" + node.schemaElement.step + "'" : "") %><%= (node.schemaElement && node.schemaElement.minLength ? " minlength='" + node.schemaElement.minLength + "'" : "") %><%= (node.schemaElement && node.schemaElement.maxLength ? " maxlength='" + node.schemaElement.maxLength + "'" : "") %><%= (node.schemaElement && node.schemaElement.required && (node.schemaElement.type !== "boolean") ? " required='required'" : "") %><%= (node.placeholder? " placeholder=" + '"' + escape(node.placeholder) + '"' : "")%> list="<%= id %>_datalist" /><datalist id="<%= id %>_datalist"><%=datalist%></datalist></div>`,
"fieldtemplate": true,
"inputfield": true,
onBeforeRender: function (data, node) {
data.datalist = ""
if (!node.schemaElement?.enum?.length) return;
const options = []
for (let item of node.schemaElement.enum) {
options.push(`<option value="${JSONFormExt.htmlentities(item)}">`)
}
data.datalist = options.join("")
},
}
/**
* Add tag elements.
* Schema must be in 'object' type
*/
JSONForm.fieldTypes['tag'] = {
"template": `<input type="text" class='jsonform-tags form-control<%= (fieldHtmlClass ? " " + fieldHtmlClass : "") %>'name="<%= node.name %>" value="<%= escape(JSON.stringify(node.value)) %>" id="<%= id %>" aria-label="<%= node.title ? escape(node.title) : node.name %>"<%= (node.disabled? " disabled" : "")%><%= (node.readOnly ? " readonly='readonly'" : "") %><%= (node.schemaElement && (node.schemaElement.step > 0 || node.schemaElement.step == "any") ? " step='" + node.schemaElement.step + "'" : "") %><%= (node.schemaElement && node.schemaElement.minLength ? " minlength='" + node.schemaElement.minLength + "'" : "") %><%= (node.schemaElement && node.schemaElement.maxLength ? " maxlength='" + node.schemaElement.maxLength + "'" : "") %><%= (node.schemaElement && node.schemaElement.required && (node.schemaElement.type !== "boolean") ? " required='required'" : "") %><%= (node.placeholder? " placeholder=" + '"' + escape(node.placeholder) + '"' : "")%> />`,
"fieldtemplate": true,
"inputfield": true,
onInsert: function (evt, node) {
const $elm = $(node.el).find(".jsonform-tags");
const whitelist = node.formElement.whitelist || node.schemaElement.enum || []
const enforceWhitelist = node.formElement.enforceWhitelist || false;
const maxTags = node.formElement.maxTags || Infinity;
const mode = node.formElement.mode; // select
//console.log("Preparing tagify for elm", $elm[0]);
const tagify = new Tagify($elm[0], {
dropdown: {
highlightFirst: true
},
whitelist: whitelist, // predefined values
enforceWhitelist: enforceWhitelist, // only allow values from the whitelist
maxTags:maxTags,
mode:mode,
originalInputValueFormat: (valuesArr)=> {
const result = [];
for (let val of valuesArr) {
result.push(val.value)
}
return JSON.stringify(result);
}
});
$elm.data("tagify", tagify);
console.log("initialized tag elm : ", $elm);
console.log("node : ", node);
},
// getFormValuesHook : function(originalValues) {
// console.log("getFormValuesHook() custom getValue's this", this);
// console.log("getFormValuesHook() original value is", originalValues);
// const thisValue = originalValues[this.key];
// const valObj = JSON.parse(thisValue || "[]");
// const result = []
// for (let val of valObj) {
// result.push(val.value)
// }
// originalValues[this.key] = result;
// console.log("getFormValuesHook(), about to return", originalValues);
// return originalValues;
// }
};
JSONForm.fieldTypes['selectfile'] = {
"template": `<input type="text" class='jsonform-selectfile form-control<%= (fieldHtmlClass ? " " + fieldHtmlClass : "") %>'name="<%= node.name %>" value="<%= escape(value) %>" id="<%= id %>" accept="<%= node.formElement.accept %>" aria-label="<%= node.title ? escape(node.title) : node.name %>"<%= (node.disabled? " disabled" : "")%><%= (node.readOnly ? " readonly='readonly'" : "") %><%= (node.schemaElement && (node.schemaElement.step > 0 || node.schemaElement.step == "any") ? " step='" + node.schemaElement.step + "'" : "") %><%= (node.schemaElement && node.schemaElement.minLength ? " minlength='" + node.schemaElement.minLength + "'" : "") %><%= (node.schemaElement && node.schemaElement.maxLength ? " maxlength='" + node.schemaElement.maxLength + "'" : "") %><%= (node.schemaElement && node.schemaElement.required && (node.schemaElement.type !== "boolean") ? " required='required'" : "") %><%= (node.placeholder? " placeholder=" + '"' + escape(node.placeholder) + '"' : "")%> />`,
"fieldtemplate": true,
"inputfield": true,
onInsert: function (evt, node) {
const $elm = $(node.el).find(".jsonform-selectfile");
$elm.attr("data-renderdvfield", "this");
var accept = node.formElement.accept || "*";
$elm.attr("accept", accept);
if (node.formElement.multiple) $elm.attr("multiple", "multiple");
if (node.formElement.directory) $elm.attr("nwdirectory", "nwdirectory");
if (node.formElement.nwsaveas) $elm.attr("nwsaveas", "nwsaveas");
const dvFields = new DVField();
dvFields.renderAll($elm);
}
};
JSONForm.fieldTypes['selectdir'] = {
"template": `<input type="text" class='jsonform-selectfile form-control<%= (fieldHtmlClass ? " " + fieldHtmlClass : "") %>'name="<%= node.name %>" value="<%= escape(value) %>" id="<%= id %>" accept="<%= node.formElement.accept %>" aria-label="<%= node.title ? escape(node.title) : node.name %>"<%= (node.disabled? " disabled" : "")%><%= (node.readOnly ? " readonly='readonly'" : "") %><%= (node.schemaElement && (node.schemaElement.step > 0 || node.schemaElement.step == "any") ? " step='" + node.schemaElement.step + "'" : "") %><%= (node.schemaElement && node.schemaElement.minLength ? " minlength='" + node.schemaElement.minLength + "'" : "") %><%= (node.schemaElement && node.schemaElement.maxLength ? " maxlength='" + node.schemaElement.maxLength + "'" : "") %><%= (node.schemaElement && node.schemaElement.required && (node.schemaElement.type !== "boolean") ? " required='required'" : "") %><%= (node.placeholder? " placeholder=" + '"' + escape(node.placeholder) + '"' : "")%> />`,
"fieldtemplate": true,
"inputfield": true,
onInsert: function (evt, node) {
const $elm = $(node.el).find(".jsonform-selectfile");
$elm.attr("data-renderdvfield", "this");
var accept = node.formElement.accept || "*";
$elm.attr("accept", accept);
if (node.formElement.multiple) $elm.attr("multiple", "multiple");
if (node.formElement.nwsaveas) $elm.attr("nwsaveas", "nwsaveas");
$elm.attr("nwdirectory", true);
const dvFields = new DVField();
dvFields.renderAll($elm);
}
};
// patch for ace field.
// load ace if ace is not defined
const aceOnInsert = JSONForm.fieldTypes['ace'].onInsert;
JSONForm.fieldTypes['ace'].onInsert = async function(evt, node) {
if (!window.ace) {
await common.loadDomScript("modules/ace/src-min-noconflict/ace.js");
}
aceOnInsert.call(this, evt, node);
}
// todo
// select file / folder field
JSONForm.fieldTypes['selectfileorfolder'] = {
"template": `<input type="text" class='jsonform-selectfile form-control<%= (fieldHtmlClass ? " " + fieldHtmlClass : "") %>'name="<%= node.name %>" value="<%= escape(value) %>" id="<%= id %>" accept="<%= node.formElement.accept %>" aria-label="<%= node.title ? escape(node.title) : node.name %>"<%= (node.disabled? " disabled" : "")%><%= (node.readOnly ? " readonly='readonly'" : "") %><%= (node.schemaElement && (node.schemaElement.step > 0 || node.schemaElement.step == "any") ? " step='" + node.schemaElement.step + "'" : "") %><%= (node.schemaElement && node.schemaElement.minLength ? " minlength='" + node.schemaElement.minLength + "'" : "") %><%= (node.schemaElement && node.schemaElement.maxLength ? " maxlength='" + node.schemaElement.maxLength + "'" : "") %><%= (node.schemaElement && node.schemaElement.required && (node.schemaElement.type !== "boolean") ? " required='required'" : "") %><%= (node.placeholder? " placeholder=" + '"' + escape(node.placeholder) + '"' : "")%> />`,
"fieldtemplate": true,
"inputfield": true,
onInsert: function (evt, node) {
const $elm = $(node.el).find(".jsonform-selectfile");
$elm.attr("data-renderdvfield", "this");
var accept = node.formElement.accept || "*";
$elm.attr("accept", accept);
if (node.formElement.multiple) $elm.attr("multiple", "multiple");
if (node.formElement.directory) $elm.attr("nwdirectory", "nwdirectory");
if (node.formElement.nwsaveas) $elm.attr("nwsaveas", "nwsaveas");
const dvFields = new DVField();
dvFields.renderAll($elm);
}
};
JSONForm.fieldTypes.fieldset.template = `<fieldset class="form-group jsonform-error-<%= keydash %> <% if (elt.expandable) { %>expandable<% } %> <%= elt.htmlClass?elt.htmlClass:"" %>" <% if (id) { %> id="<%= id %>"<% } %>><% if (node.title || node.legend) { %><legend role="treeitem" aria-expanded="false"><%= node.title || node.legend %></legend><% } %><% if (elt.expandable) { %><div class="form-group"><% } %><div class="fieldset-content"><%= children %></div><% if (elt.expandable) { %></div><% } %></fieldset>`
}