/**
* Save fields to server
*
* @param {boolean} [includeAll] if set to true then export all shown or hidden fields
* @param {function} [callback] Callback for save complete
* @param {boolean} [force] Force save and ignore changes status
* @return {Object[]} Field objects list
*/
function saveFields(includeAll, callback, force)
{
if(typeof includeAll === 'function')
{
callback = includeAll;
includeAll = false;
}
var fieldsList = [];
var changedFields = [];
var revertChanges = function()
{
for(var i = 0; i < changedFields.length; ++i)
{
changedFields[i].changed = true;
}
};
var errorsCount = 0;
for(var i = 0; i < fields.length; ++i)
{
var originField = fields[i];
if(originField.changed)
{
originField.changed = false;
changedFields.push(originField);
}
if(!includeAll && originField.show !== '1') continue;
var field = $.extend({}, originField);
if(originField.errors && originField.errors.$length) errorsCount++;
field.order = i + 1;
if(field.id[0] === '_') delete field.id;
if(field.type === 'decimal')
{
field.length = field.integerDigits + ',' + field.decimalDigits;
}
delete field.unsaved;
delete field._options;
delete field.errors;
delete field.changed;
delete field.rules;
delete field.optionClass;
if($.isArray(field.options))
{
var options = {};
for(var j = 0; j < field.options.length; ++j)
{
var option = field.options[j];
if(option.value) options[option.value] = option.text;
}
field.options = options;
}
if($.isArray(field.layoutRules))
{
field.layoutRules = field.layoutRules.join(',');
}
fieldsList.push(field);
}
if(!force && !changedFields.length) return;
if(errorsCount)
{
revertChanges();
$('#editor').addClass('highlight-errors');
setTimeout(function()
{
$('#editor').removeClass('highlight-errors');
}, 5000);
return new $.zui.Messager(window.validateMessages.failSummary.replace('%s', errorsCount),
{
type: 'danger',
icon: 'bell',
placement: 'center',
}).show();
}
var link = createLink('workflow', 'ui', 'module=' + window.flowModule + '&action=' + window.action);
$.post(link, {fields: JSON.stringify(fieldsList)}, function(response)
{
try {response = JSON.parse(response);}
catch(error)
{
response = response ? response : window.unknownError;
new $.zui.Messager(response,
{
type: 'danger',
icon: 'bell',
placement: 'center',
time: 10000
}).show();
revertChanges();
if(callback) callback(false, response);
return;
}
if(response.result == 'fail')
{
if(typeof response.message === 'string') bootbox.alert(response.message);
else if($.isPlainObject(response.message))
{
var errors = {};
if(response.field) errors[response.field] = response.message;
else errors = response.message;
window.updateFieldsErrors(errors);
}
revertChanges();
if(callback) callback(false, response);
}
else
{
$('#saveBtn').popover(
{
trigger: 'manual',
content: response.message,
tipClass: 'popover-success popover-form-result',
placement: 'left'
}).popover('show');
setTimeout(function(){$('#saveBtn').popover('destroy')}, 2000);
if(callback) callback(true, response);
}
});
return true;
}
/**
* Get default options list of specific option type
*
* @param {Object} field field object
* @param {Function} callback callback
* @return {Object} return default options key-value with a object
*/
function getDefaultsOfOption(field, callback)
{
/* Fetch default options from server, then call callback on ready */
var sql = window.btoa(encodeURI(field.sql));
var control = window.btoa(encodeURI(field.control));
var optionType = field.options;
var type = field.type;
var value = window.btoa(encodeURI(field.defaultValue));
var link = createLink('workflowfield', 'ajaxGetDefaultControl', 'mode=quick&control=' + control + '&optionType=' + optionType + '&type=' + type + '&sql=' + sql + '&sqlVars=&elementName=&default=' + value);
$.getJSON(link, callback);
}
function initDefault(field, isCustomOptions)
{
var $fieldDefaultValue = $('#fieldDefaultValue');
var chosen = $fieldDefaultValue.data('chosen');
var picker = $fieldDefaultValue.data('zui.picker');
if($fieldDefaultValue.find('option[value=ajax_search_more]').length == 1)
{
$fieldDefaultValue.find('option[value=ajax_search_more]').remove();
if(chosen) chosen.destroy();
var control = window.btoa(encodeURI(field.control));
var optionType = field.options;
var type = field.type;
var sql = '';
var url = createLink('workflowfield', 'ajaxGetMoreDefault', 'mode=advanced&control=' + control + '&optionType=' + optionType + '&type=' + type + '&sql=' + sql + '&sqlVars=&search={search}');
initPicker($('#fieldDefaultValue'), {remote: url});
}
else
{
if(picker) picker.destroy();
if(chosen)
{
$fieldDefaultValue.trigger('chosen:updated');
}
else
{
$fieldDefaultValue.chosen({allow_single_deselect: true});
}
}
}
/**
* Get default field properties by control type
*
* @param {String} controlType
* @return {Object}
*/
function getDefaultFieldByControl(controlType)
{
var field =
{
type: fieldDefault.type,
optionClass: fieldDefault.optionClass,
integerDigits: fieldDefault.integerDigits,
decimalDigits: fieldDefault.decimalDigits,
};
switch(controlType)
{
case 'label' :
field.type = 'mediumint';
field.optionClass = 'integer';
break;
case 'formula' :
case 'decimal' :
field.type = 'decimal';
field.optionClass = 'decimal';
break;
case 'integer' :
field.type = 'int';
field.optionClass = 'integer';
break;
case 'multi-select' :
case 'checkbox' :
case 'textarea' :
case 'richtext' :
field.type = 'text';
field.optionClass = 'text';
break;
case 'date' :
field.type = 'date';
field.optionClass = 'date';
break;
case 'datetime' :
field.type = 'datetime';
field.optionClass = 'time';
break;
}
return field;
}
function removeOptionError(field)
{
if(field.errors.options)
{
delete field.errors.options;
field.errors.$length --;
$('#field-' + field.id).toggleClass('has-error', !!(field.errors && field.errors.$length))
$('#fieldOptionsMessage').hide();;
}
}
/* https://tc39.github.io/ecma262/#sec-array.prototype.findIndex */
if (!Array.prototype.findIndex)
{
Object.defineProperty(Array.prototype, 'findIndex',
{
value: function(predicate)
{
if(this == null) throw new TypeError('"this" is null or not defined');
var o = Object(this);
var len = o.length >>> 0;
if(typeof predicate !== 'function') throw new TypeError('predicate must be a function');
var thisArg = arguments[1];
var k = 0;
while(k < len)
{
var kValue = o[k];
if(predicate.call(thisArg, kValue, k, o)) return k;
k++;
}
return -1;
}
});
}
$(function()
{
var isForm = uiMode === 'form';
var isView = uiMode === 'view';
var isBatchForm = uiMode === 'batchForm';
var canSetWidth = uiMode === 'browse' || isBatchForm;
var canSetPosition = canSetWidth || uiMode === 'view';
var $previewBox = $('#editorPreview');
var $preview = $(isForm ? '#uiPreview' : isView ? '#uiViewWrapper' : '#uiListHeader');
var $infoPreview = isView ? $('#uiInfoViewPreview') : null;
var $basicPreview = isView ? $('#uiBasicViewPreview') : null;
var $listPreview = canSetWidth ? $('#uiListPreviewItems') : null;
var $filedEditForm = $('#filedEditForm');
var remoteOptions = window.remoteOptions = fieldDefaultOptions || {};
var hasActionsInList;
var activedField;
/* Format options to standart, like [{text: 'Today', value: 'today'}, ...] */
var formatOptions = function(options)
{
if(typeof options === 'string')
{
options = options.split(',');
}
if($.isArray(options) || $.isPlainObject(options))
{
var optionsList = [];
$.each(options, function(value, text)
{
optionsList[text.length ? 'push' : 'unshift']({value: value, text: text});
});
options = optionsList;
}
return options;
};
/* Get keys of a object */
var getObjectKeys = function(obj, filter)
{
var keys = [];
$.each(obj, function(key)
{
if(filter && !filter(key)) return;
keys.push(key);
});
return keys;
};
/* Get field index in list by id or field code */
var getFieldIndex = function(id)
{
if(typeof id === 'number') id = String(id);
return fields.findIndex(function(field)
{
return field.id === id || field.field === id;
});
};
/* Get field object by id or field code */
var getField = function(id)
{
var index = getFieldIndex(id);
return index > -1 ? fields[index] : null;
};
/* Check whether the field is buildin */
var isBuildInField = function(field)
{
return field.buildin === '1' || defaultFields[field.field];
};
/* Get field select control type, return 'multi', 'single' or false */
var getFieldSelectType = function(field)
{
if(isBuildInField(field) && field.field !== 'status') return false;
if(field.control === 'multi-select' || field.control === 'checkbox') return field.options !== 'prevModule' ? 'multi' : 'text';
else if(field.control === 'select' || field.control === 'radio') return field.options !== 'prevModule' ? 'single' : 'text';
return false;
};
/* Create preview control element for form mode */
var createFieldControl = function(field, onlyHtml)
{
var controlType = field.control;
var html = '';
switch(controlType)
{
case 'label':
html = '
';
break;
case 'textarea':
case 'richtext':
html = '';
break;
case 'select':
html = '';
break;
case 'multi-select':
html = '';
break;
case 'checkbox':
html = '';
break;
case 'radio':
html = '';
break;
case 'file':
html = '
';
break;
default:
html = '';
}
return onlyHtml ? html : $(html);
};
/* Update field preview control for form mode */
var updateFieldControl = function($wrapper, field)
{
if(field.field === 'file') return;
var controlType = field.control;
var readonly = field.readonly;
var defaultValue = field.defaultValue;
switch(controlType)
{
case 'label':
$wrapper.find('.form-control-static').text(defaultValue);
break;
case 'textarea':
case 'richtext':
$wrapper.find('textarea').val(defaultValue);
break;
case 'select':
case 'multi-select':
var $select = $wrapper.find('select');
$select.empty();
defaultValue = ',' + defaultValue + ',';
if(typeof field.options === 'object')
{
$.each(field.options, function(_, option)
{
var $option = $('').attr('value', option.value).text(option.text);
if(defaultValue.indexOf(',' + option.value + ',') != -1) $option = $option.prop('selected', 'selected');
$select.append($option);
});
}
else
{
if(field.optionsData)
{
$.each(field.optionsData, function(value, text)
{
var $option = $('').attr('value', value).text(text);
if(defaultValue.indexOf(',' + value + ',') != -1) $option = $option.prop('selected', 'selected');
$select.append($option);
});
}
}
if(!$select.data('chosen')) $select.chosen();
else $select.trigger('chosen:updated');
break;
case 'checkbox':
case 'radio':
var $list = $wrapper.find('.' + controlType + '-list');
$list.empty();
var name = 'field-' + controlType + '-' + field.id;
var options = typeof field.options === 'object' ? field.options : [{value: '__example', text: ''}];
$.each(options, function(_, option)
{
var $label = $('');
var $option = $('').attr({name: name, value: option.value});
$label.append($option).append($('').text(option.text));
if(option.value === '__example') $label.find('span').addClass('example-text-holder');
$list.append($label);
});
break;
case 'date':
var $input = $wrapper.find('.form-control');
if(defaultValue == 'currentTime') defaultValue = window.currentDate;
$input.val(defaultValue).attr('readonly', readonly === '1' ? 'readonly' : null);
if(!$input.data('datetimepicker')) $input.datepicker();
break;
case 'datetime':
var $input = $wrapper.find('.form-control');
if(defaultValue == 'currentTime') defaultValue = window.currentTime;
$input.val(defaultValue).attr('readonly', readonly === '1' ? 'readonly' : null);
if(!$input.data('datetimepicker')) $input.datetimepicker();
break;
default:
$wrapper.find('.form-control').val(defaultValue);
}
};
/* Update field detail view item for view mode */
var updateFieldView = function($wrapper, field)
{
var $label = $wrapper.find('.field-label');
$label.text(field.name);
if(field.position !== $wrapper.closest('.view-dropbox').data('position'))
{
var $viewBox = field.position === 'basic' ? $basicPreview : $infoPreview;
var inserted = false;
$viewBox.find('.field-view-item').each(function()
{
var $field = $(this);
if(field.order >= $field.data('order'))
{
$field.after($wrapper);
inserted = true;
return false;
}
});
if(!inserted) $viewBox.append($wrapper);
}
};
/* Update field preview control for list column */
var updateFieldColumn = function($wrapper, field)
{
var $label = $wrapper.find('.field-col-item-label');
$label.text(field.name);
$wrapper.css(
{
width: field.width,
textAlign: field.position
});
};
var createListPreviewItem = function(field)
{
return isBatchForm ? '