/**
* A data field that deals with array values. See the {@link #itemType} config for controlling
* the array elements.
*
* @example
* Ext.define('Task', {
* extend: 'Ext.data.Model',
* fields: [{
* name: 'milestoneDates',
* type: 'array',
* itemType: {
* type: 'date',
* dateFormat: 'Y-m-d'
* }
* }]
* });
*
* var record = Ext.create('Task', { milestoneDates: [
* '2010-01-01',
* '2010-02-01',
* '2010-03-01'
* ]}), value = record.get('milestoneDates');
*
* Ext.toast(value.join(', '));
*
*/
Ext.define('Ext.data.field.Array', {
extend: 'Ext.data.field.Field',
alias: 'data.field.array',
isArrayField: true,
/**
* @cfg {String/Object/Ext.data.field.Field} itemType
*
* Controls the individual elements of the array. This is a field type or configuration
* that is used to {@link #collate}, {@link #compare}, {@link #isEqual compare equality},
* {@link #convert} and {@link #deserialize} each element.
*/
itemType: {
type: 'auto'
},
getType: function() {
return 'array';
},
collate: function(v1, v2) {
return this.collateOrCompare(v1, v2, 'collate');
},
compare: function(v1, v2) {
return this.collateOrCompare(v1, v2, 'compare');
},
convert: function(v) {
return this.doForEach((v || v === 0) && !Ext.isArray(v) ? [v] : v, 'convert');
},
serialize: function(value) {
return this.doForEach(value, 'serialize');
},
/**
* @private
*/
getItemField: function() {
var me = this,
t = me.itemType;
if (!me.itemField) {
if (typeof t === 'string') {
t = {
type: t
};
}
else if (!(t && t.isDataField)) {
t = Ext.apply({
type: 'auto'
}, t);
}
me.itemField = Ext.data.field.Field.create(t);
}
return me.itemField;
},
/**
* @private
*/
doForEach: function(v, fn) {
if (!v) {
return this.allowNull ? null : [];
}
// eslint-disable-next-line vars-on-top
var len = v.length,
ret = Array(len),
field = this.getItemField(),
i;
for (i = 0; i < len; ++i) {
ret[i] = field[fn] ? field[fn](v[i]) : v[i];
}
return ret;
},
/**
* @private
*/
collateOrCompare: function(v1, v2, fn) {
var field = this.getItemField(),
i, len1, len2, len, result;
if ((!v1 && !v2) || (v1 === v2)) {
return 0;
}
if (!v1 || !v2) {
return v1 ? 1 : -1;
}
len1 = v1.length;
len2 = v2.length;
len = Math.min(len1, len2);
for (i = 0; i < len; ++i) {
result = field[fn](v1[i], v2[i]);
if (result !== 0) {
return result;
}
}
return len1 === len2 ? 0 : (len1 < len2 ? -1 : 1);
}
});