json-object-editor
Version:
JOE the Json Object Editor | Platform Edition
340 lines (316 loc) • 16.3 kB
JavaScript
function FormBuilder(){
var self = this;
this.submission = function(data,req){
var fid =data.formid;
if(!fid){
return {errors:'no form id',failedat:'submissionhandler'};
}
var form = JOE.Cache.findByID('form',fid);
var source = req.headers.referer || req.headers.host;
var payload = {
source:source,
//headers:req.headers,
data:data,
message:'Form Submitted',
formname:form.name
};
if(!form){
return {errors:'form not found',failedat:'submissionhandler'};
}
if(form.save_submission){
var visitorid = (form.visitor_id_field)?data.submission[form.visitor_id_field]:'';
var submission_date = (form.submission_date_field)?data.submission[form.submission_date_field]:'';
var sub = {
data:data.submission,
form_name:form.name,
source:source,
form:fid,
submission_date,
visitor:visitorid
};
sub.joeUpdated = new Date().toISOString();
sub.itemtype = 'submission';
if(form.upsert_submission){
logit(`running upsert ${visitorid} | ${submission_date} `);
var submissionExists = $J.search({visitor:visitorid,submission_date,itemtype:'submission'});
if(submissionExists.length){
console.log('submission found',submissionExists);
sub._id = submissionExists[0]._id;
sub.created = submissionExists[0].created || sub.joeUpdated;
JOE.Storage.save(sub,'submission',function(err,data){
if(!err){
logit('submission updated')
}
},{history:false});
return {
message:'successfully updated existing submission',
'_id':submissionExists[0]._id
};
}
}
sub.created = sub.joeUpdated;
sub._id = cuid();
JOE.Storage.save(sub,'submission',function(err,data){
if(!err){
logit('submission saved')
}
},{history:false});
}
if(form.server_action){
try{
var server_action = eval('('+form.server_action+')');
var tpayload = server_action(data,form,req);
payload = tpayload;
}catch(e){
return {errors:'plugin error: '+e,failedat:'plugin'};
}
}
return payload;
},
this.default = this.render = function(data,req){
try{
var formid = (req.query.formid||req.query.form||data.formid||data.form);
console.log('form:'+formid);
var form = JOE.Cache.findByID('form',formid);
var form_copy = $c.merge({},form);
var hostname = JOE.webconfig.hostname || 'localhost';
delete form_copy.form_preview;
form_copy._port = (!JOE.webconfig.https)?JOE.webconfig.port:'';
var port =form_copy.port= (!JOE.webconfig.https)?':'+JOE.webconfig.port:'';
if(JOE.webconfig.PORT){
form_copy._fulljoepath =JOE.webconfig.joepath;
var _joereqpath = form_copy._joereqpath = JOE.webconfig.joepath;
if(data.remote && JOE.webconfig.hostname){
_joereqpath=((JOE.webconfig.hostname.indexOf('http')== -1)?'//':'')+JOE.webconfig.hostname+_joereqpath;
}
var fullhostname = form_copy.fullhostname = '';
console.log(data);
console.log(_joereqpath);
}else{
var protocol =form_copy.protocol =(JOE.webconfig.https)?'https://':'//';
form_copy._fulljoepath =protocol+hostname+port+JOE.webconfig.joepath;
var _joereqpath = form_copy._joereqpath = protocol+hostname+port+JOE.webconfig.joepath;
var fullhostname = form_copy.fullhostname = protocol+hostname+port;
}
//console.log(fullhostname);
//console.log('urlparams',req.query);
var template =
`<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<script>var web_dir="${fullhostname}/JsonObjectEditor/"</script>
<link rel="stylesheet" href="${_joereqpath}capp/capp.css"/>
<script src="${_joereqpath}_joeinclude.js"></script>
<script src="${_joereqpath}capp/capp.js"></script>`+
"<script>var __apiport = '"+fullhostname+"'; "
+`var JOE = new JsonObjectEditor();_joe.addStylesheet('${_joereqpath}css/form-styles.css');</script>`+
"<form class='joe-form' data-id='${_id}' onsubmit='return __onSubmit(this);'>";
var section_questions,question,input_rendering,required,question_name,fieldname;
form.sections.map(function(section,index){
section_questions = form.questions[index] || [];
template += `<fieldset id="${section.id}"><section-label>${section.name}</section-label>`;
section_questions.map(function(qid){
question = JOE.Cache.findByID('question',qid)||{};
try{
required = question.required;
fieldname = question.fieldname || question.name;
question_name = `<question-name> ${question.title || question.name}`+((required && '<req-star>*</req-star>' )||'')+'</question-name>';
template +=fillTemplate('<form-question data-name="'+fieldname+'" data-label="${name}" class="'+(required&&'required'||'')+'"><label for="'+fieldname+'"> '+question_name
+(question.info && ' <question-info> ${info}</question-info>' || ''),question);
input_rendering = '';
switch(question.question_type){
case 'oneline':
input_rendering = '<input type="text" name="'+fieldname+'" id="'+fieldname+'">';
break;
case 'number':
input_rendering = '<input type="number" name="'+fieldname+'" id="'+fieldname+'">';
break;
case 'password':
input_rendering = '<input type="password" name="'+fieldname+'" id="'+fieldname+'">';
break;
case 'textarea':
input_rendering = '<textarea name="'+fieldname+'" id="'+fieldname+'"></textarea>';
break;
case 'content':
var content_eval;
try{
content_eval = eval('('+question.content+')');
}catch(e){
content_eval = question.content;
}
input_rendering = (typeof content_eval == 'function')?
content_eval({question:question,form:form}):content_eval;
break;
case 'select':
var opts = question.options||[];
var ds = question.question_dataset;
//TODO: get values from question dataset
if(ds && ds != "none"){
if(JOE.Data[ds]){
logit('DS '+ds+' found: '+JOE.Data[ds].length);
opts = JOE.Data[ds];
if(opts && opts[0] && opts[0].name){
logit('sorting by name');
$c.sortBy(opts,"name");
}
}else{
input_rendering =' remote dataset: '+ds;
break;
}
}
input_rendering = '<select name="'+fieldname+'" id="'+fieldname+'">';
opts.map(function(opt){
//console.log(opt);
let opt_display = (opt.label||opt.name||opt.value);
let opt_value = (opt._id||opt.value);
if(question.option_template){
opt_display = fillTemplate(question.option_template,opt);
}
if(question.value_template){
opt_value = fillTemplate(question.value_template,opt);
}
input_rendering += `<option value="${opt_value}">${opt_display}</option>`;
});
input_rendering += '</select>';
break;
case 'multiple':
var opts = question.options||[];
var ds = question.question_dataset;
if(ds && ds != "none"){
if(JOE.Data[ds]){
opts = JOE.Data[ds];
}else{
input_rendering =' remote dataset: '+ds;
break;
}
}
opts.map(function(opt){
input_rendering += `<label class="form-checkbox" >
<input type="checkbox" name="${fieldname}" value="${(opt.value||opt._id)}" />${(opt.label||opt.name||opt.value)}
</label>`;
});
break;
}
template+=input_rendering+'</label></form-question>';
}catch(e){
template +='<div>Error rendering question:'+fieldname+'|'+question._id+'</div>';
}
})
template +='</fieldset>';
});//end section fieldsets
//add complete
template += '<input type="submit" value="'+
(form.form_button_label||'submit')+'" onclick="">';
template += "</form>";
var payload = fillTemplate('<h2 id="formTitle">${name}</h2>'+template,form_copy);
if(form.includes){
var i_html = '';
form.includes.map(inc=>{
let include = global.$J.get(inc);
switch(include.filetype){
case 'css':
i_html +=`<link rel="stylesheet" href="/_include/${inc}"/>`;
break;
case 'js':
i_html +=`<script src="/_include/${inc}"></script>`;
break;
}
})
payload = i_html+payload;
}
var form_str = '<script>var __form='+JSON.stringify(form_copy)+'</script>';
function __onFormRender(){
//replace ajax-field?
}
function __onSubmit(formdom){
try{
var $ = $ || jQuery;
var user_submission = {};
var required = [];
var errors=[];
$(formdom).find('form-question').each(function(){
var name = $(this).data('name');
var label = $(this).data('label');
var req =$(this).hasClass('required');
var dom = $('form *[name=\''+name+'\']');
var val = dom && dom.val();
if(name && dom){
if(dom.length > 1){//checkboxgroup
val = [];
$("form *[name='"+name+"']:checked")
.each(function(){
val.push($(this).val());
});
}
user_submission[name] = val;
if(req){
if(!user_submission[name] || !user_submission[name] == 'undefined'|| !user_submission[name].length){
errors.push(label+' is required')
}
required.push(name);
}
}else{
alert(name+' field not found')
}
});
if(__form.validate){
try{
var val_func = eval('('+__form.validate+')');
var validates = val_func(user_submission);
if(validates !== true){
errors.push(validates || 'error validating form');
}
}catch(e){
errors.push('error running form validation: '+e);
}
}
//alert(JSON.stringify(user_submission,' ',' '));
if(errors.length){
alert('submission error:\n '+errors.join('\n '));
return false;
}
}catch(e){
alert('error:'+e);
return false;
}
var form_submission={
formid:__form._id,
submission:user_submission
};
var hostname = __form.hostname || location.hostname;
$.ajax({
url:__form.fullhostname+'/API/plugin/formBuilder/submission',
data:form_submission,
dataType:'jsonp',
success:function(data){
if(data.errors){
alert(data.errors);
return;
}
var completeAction;
try{
completeAction = eval('('+ __form.callback.replace(/\;n/g,';')+')');
}catch(e){
}
if(completeAction){
completeAction(data);
}else{
alert((typeof data == 'object')?JSON.stringify(data,' ',' '):data);
}
}
})
return false;
//check requireds
//run form.validate
//sendPayload
}
var additional_functions ='<script>'+ __onSubmit.toString()+'</script>';
if(data.remote){
return {response:payload+form_str+additional_functions,form:form_copy};
}
return payload+form_str+additional_functions;
}catch(e){
return 'Error rendering form: '+e;
}
}//end bodycontent
return self;
}
module.exports = new FormBuilder();