/**
* @module app/models/Field
*/
define(
[
'knockout',
'common'
],
function(ko, lib) {
/**
* This will map selected properties into an observable or an observableArray, and the rest will be copied or ignored
* @constructor
* @alias module:app/models/Field
* @param {Object} fieldObj The valid field settings object
*
* @example <caption>Example usage for Field</caption>
* //use it before adding the field to the array of fields
* var field = new Field(field_settings);
* //then add it to the observableArray that is responsible for showing the fields
* //for example you have fields_array variable
* var fields_array = ko.observableArray([]);
* fields_array(field);
*
* @see module:templates/index
*
* @requires knockout
* @requires common
*/
function Field(fieldObj) {
var prop;
var UUID = lib.createUuid();
/**
* The properties that will be ignored, or they're just here if the value needs only to be copied
* @type {Array}
*/
var ignoredProperties = [
'id',
'key',
'childFields',
'name',
'parent',
'parents',
'display_order',
'created_at',
'updated_at',
'deleted_at',
'created_by',
'updated_by',
'deleted_by'
];
/**
* The property to be casted to the specified type
* @type {Object}
*/
var casts = {
options: []
};
var arrProp = null;
for (prop in fieldObj) {
if (fieldObj.hasOwnProperty(prop) && !(ko.isObservable(fieldObj[prop]))) {
/**
* The field type
* @type {Number}
*/
this.key = fieldObj.key;
/**
* The name of the field generated using common#createUuid
* @see common#createUuid
* @type {String}
*/
this.name = fieldObj.name || UUID;
/**
* The direct parent of this field, will hold it's parent name
* @type {String}
*/
this.parent = fieldObj.parent;
/**
* A flag used to determine if the field controls(edit, delete, drag) will be displayed
* @type {Boolean}
*/
this.showControls = typeof fieldObj.showControls === 'undefined' ? true : fieldObj.showControls;
/**
* If the module:js/models/Field#showNumbering is true, this will contain the numbering order of the field
* @see module:js/models/Field#showNumbering
* @type {Number}
*/
this.numbering = ko.observable(false);
/**
* A flag for the numbering visibility
* @type {Boolean}
*/
this.showNumbering = false;
/**
* A flag to mark the field as a repeatable, used on the report editing where the user can add multiple copies of the field
* @type {Boolean}
*/
this.repeatable = ko.observable(fieldObj.repeatable || false);
/**
* The child field(s) of this field
* @type {Array}
*/
this.childFields = null;
if (!ko.isObservable(fieldObj.childFields)) {
this.childFields = ko.observableArray([]);
}
if (fieldObj.id) {
this.id = fieldObj.id;
}
// ------------------------------------------------------
// Check if the current prop is not an ignored property
// ------------------------------------------------------
if (ignoredProperties.indexOf(prop) === -1) {
if (casts[prop] && casts[prop] instanceof Array) {
arrProp = fieldObj[prop];
try {
arrProp = JSON.parse(arrProp)
} catch (err) {
// console.error('Field model: ', err);
}
if (arrProp instanceof Array && arrProp.length) {
// converts this property into an observableArray
this[prop] = ko.observableArray(arrProp.map(function(item) {
// and the child properties will be converted to an observable
for (var prop in item) {
if (!(ko.isObservable(item[prop]))) {
item[prop] = ko.observable(item[prop]);
}
}
return item;
}));
} else {
this[prop] = ko.observableArray([]);
}
} else {
this[prop] = ko.observable(fieldObj[prop]);
}
} //END: if
}
} // END: for in
// -----------------------
// Subscriptions: START
// -----------------------
if (this.showNumbering && ko.isObservable(this.showNumbering)) {
this.showNumbering.subscribe(function(value) {
ko.postbox.publish('numberingToggled', {
field: this,
parent: null
});
if (!value && this.repeatable()) {
this.repeatable(false);
}
}, this);
}
if (this.max_chars && ko.isObservable(this.max_chars)) {
this.max_chars.subscribe(function(len) {
if (len) {
this.value(this.value().substring(0, len));
}
}, this);
}
if (this.fg_changed && ko.isObservable(this.fg_changed)) {
this.fg_changed.subscribe(function(changed) {
this.foreground(changed ? this.fg_class() : '');
}, this);
}
if (this.bg_changed && ko.isObservable(this.bg_changed)) {
this.bg_changed.subscribe(function(changed) {
this.background(changed ? this.fg_class() : '');
}, this);
}
// -----------------------
// Subscriptions: END
// -----------------------
}
return Field;
});