306 lines
8.9 KiB
JavaScript
306 lines
8.9 KiB
JavaScript
|
|
(function() {
|
|
'use strict';
|
|
|
|
angular
|
|
.module('merlin')
|
|
.factory('merlin.field.models', merlinFieldModels);
|
|
|
|
merlinFieldModels.$inject = ['merlin.utils', 'merlin.panel.models', '$http'];
|
|
|
|
function merlinFieldModels(utils, panels, $http) {
|
|
var wildcardMixin = Barricade.Blueprint.create(function() {
|
|
return this;
|
|
});
|
|
|
|
var viewChoicesMixin = Barricade.Blueprint.create(function() {
|
|
var self = this;
|
|
var dropDownLimit = this._dropDownLimit || 5;
|
|
var values, labels, items, isDropDown;
|
|
|
|
function fillItems() {
|
|
values = self.getEnumValues();
|
|
labels = self.getEnumLabels();
|
|
items = {};
|
|
|
|
if (values) {
|
|
values.forEach(function (value, index) {
|
|
items[value] = labels[index];
|
|
});
|
|
}
|
|
}
|
|
|
|
this.getLabel = function(value) {
|
|
if ( angular.isUndefined(values) ) {
|
|
fillItems();
|
|
}
|
|
return items[value];
|
|
};
|
|
|
|
this.getValues = function() {
|
|
if ( angular.isUndefined(values) ) {
|
|
fillItems();
|
|
}
|
|
return values;
|
|
};
|
|
|
|
this.resetValues = function() {
|
|
values = undefined;
|
|
};
|
|
|
|
this.isDropDown = function() {
|
|
// what starts its life as being dropdown / not being dropdown
|
|
// should remain so forever
|
|
if ( angular.isUndefined(isDropDown) ) {
|
|
isDropDown = !this.isEmpty() && this.getValues().length < dropDownLimit;
|
|
}
|
|
return isDropDown;
|
|
};
|
|
|
|
this.setType('choices');
|
|
return this;
|
|
});
|
|
|
|
/* Html renderer helper. The main idea is that fields with simple (or plain)
|
|
structure (i.e. Atomics = string | number | text | boolean and list or
|
|
dictionary containing just Atomics) could be rendered in one column, while
|
|
fields with non plain structure should be rendered in two columns.
|
|
*/
|
|
var plainStructureMixin = Barricade.Blueprint.create(function() {
|
|
this.isPlainStructure = function() {
|
|
if (this.getType() == 'frozendict') {
|
|
return false;
|
|
}
|
|
if (!this.instanceof(Barricade.Arraylike) || !this.length()) {
|
|
return false;
|
|
}
|
|
return !this.get(0).instanceof(Barricade.Container);
|
|
};
|
|
return this;
|
|
});
|
|
|
|
var modelMixin = Barricade.Blueprint.create(function(type) {
|
|
var isValid = true;
|
|
var isValidatable = false;
|
|
this.value = function() {
|
|
if ( !arguments.length ) {
|
|
if ( isValidatable ) {
|
|
return isValid ? this.get() : undefined;
|
|
} else {
|
|
return this.get();
|
|
}
|
|
} else {
|
|
this.set(arguments[0]);
|
|
isValid = !this.hasError();
|
|
}
|
|
};
|
|
this.id = utils.getNewId();
|
|
|
|
this.getType = function() {
|
|
return type;
|
|
};
|
|
|
|
this.setValidatable = function(validatable) {
|
|
isValidatable = validatable;
|
|
};
|
|
|
|
this.setType = function(_type) {
|
|
type = _type;
|
|
};
|
|
|
|
this.isAdditive = function() {
|
|
return this.instanceof(Barricade.Arraylike);
|
|
};
|
|
|
|
this.isAtomic = function() {
|
|
return !this.instanceof(Barricade.Container);
|
|
};
|
|
this.title = function() {
|
|
var title = utils.getMeta(this, 'title');
|
|
if ( !title ) {
|
|
if ( this.instanceof(Barricade.ImmutableObject) ) {
|
|
if ( this.getKeys().indexOf('name') > -1 ) {
|
|
return this.get('name').get();
|
|
}
|
|
}
|
|
title = utils.makeTitle(this.getID()) || '';
|
|
}
|
|
return title;
|
|
};
|
|
wildcardMixin.call(this);
|
|
if ( this.getEnumValues ) {
|
|
viewChoicesMixin.call(this);
|
|
}
|
|
return this;
|
|
});
|
|
|
|
function meldGroup() {
|
|
if ( utils.getMeta(this, 'group') ) {
|
|
panels.groupmixin.call(this);
|
|
}
|
|
}
|
|
|
|
var stringModel = Barricade.Primitive.extend({
|
|
create: function(json, parameters) {
|
|
var self = Barricade.Primitive.create.call(this, json, parameters);
|
|
return modelMixin.call(self, 'string');
|
|
}
|
|
}, {'@type': String});
|
|
|
|
var textModel = Barricade.Primitive.extend({
|
|
create: function(json, parameters) {
|
|
var self = Barricade.Primitive.create.call(this, json, parameters);
|
|
return modelMixin.call(self, 'text');
|
|
}
|
|
}, {'@type': String});
|
|
|
|
var numberModel = Barricade.Primitive.extend({
|
|
create: function(json, parameters) {
|
|
var self = Barricade.Primitive.create.call(this, json, parameters);
|
|
return modelMixin.call(self, 'number');
|
|
}
|
|
}, {'@type': Number});
|
|
|
|
var listModel = Barricade.Array.extend({
|
|
create: function(json, parameters) {
|
|
var self = Barricade.Array.create.call(this, json, parameters);
|
|
|
|
modelMixin.call(self, 'list');
|
|
|
|
self.add = function() {
|
|
self.push(undefined, parameters);
|
|
};
|
|
meldGroup.call(self);
|
|
plainStructureMixin.call(self);
|
|
return self;
|
|
}
|
|
}, {'@type': Array});
|
|
|
|
var frozendictModel = Barricade.ImmutableObject.extend({
|
|
create: function(json, parameters) {
|
|
var self = Barricade.ImmutableObject.create.call(this, json, parameters);
|
|
|
|
modelMixin.call(self, 'frozendict');
|
|
meldGroup.call(self);
|
|
plainStructureMixin.call(self);
|
|
return self;
|
|
}
|
|
}, {'@type': Object});
|
|
|
|
var dictionaryModel = Barricade.MutableObject.extend({
|
|
create: function(json, parameters) {
|
|
var self = Barricade.MutableObject.create.call(this, json, parameters);
|
|
var _elClass = self._elementClass;
|
|
var baseKey = utils.getMeta(_elClass, 'baseKey') || 'key';
|
|
var baseName = utils.getMeta(_elClass, 'baseName') || utils.makeTitle(baseKey);
|
|
|
|
modelMixin.call(self, 'dictionary');
|
|
plainStructureMixin.call(self);
|
|
|
|
function initKeyAccessor(value) {
|
|
value.keyValue = function () {
|
|
if ( arguments.length ) {
|
|
value.setID(arguments[0]);
|
|
} else {
|
|
return value.getID();
|
|
}
|
|
};
|
|
}
|
|
|
|
self.each(function(key, value) {
|
|
initKeyAccessor(value);
|
|
}).on('change', function(op, index) {
|
|
if (op === 'add' || op === 'set') {
|
|
initKeyAccessor(self.get(index));
|
|
}
|
|
});
|
|
|
|
self.add = function(newID) {
|
|
var regexp = new RegExp('(' + baseKey + ')([0-9]+)');
|
|
var newValue;
|
|
newID = newID || baseKey + utils.getNextIDSuffix(self, regexp);
|
|
if ( _elClass.instanceof(Barricade.ImmutableObject) ) {
|
|
if ( 'name' in _elClass._schema ) {
|
|
var nameNum = utils.getNextIDSuffix(self, regexp);
|
|
newValue = {name: baseName + nameNum};
|
|
} else {
|
|
newValue = {};
|
|
}
|
|
} else { // usually, it's either frozendict inside or string
|
|
newValue = '';
|
|
}
|
|
self.push(newValue, utils.extend(self._parameters, {id: newID}));
|
|
};
|
|
self.empty = function() {
|
|
for ( var i = this._data.length; i > 0; i-- ) {
|
|
self.remove(i - 1);
|
|
}
|
|
};
|
|
self.resetKeys = function(keys) {
|
|
self.empty();
|
|
keys.forEach(function(key) {
|
|
self.push(undefined, {id: key});
|
|
});
|
|
};
|
|
self.removeItem = function(key) {
|
|
self.remove(self.getPosByID(key));
|
|
};
|
|
meldGroup.call(self);
|
|
return self;
|
|
}
|
|
}, {'@type': Object});
|
|
|
|
var linkedCollectionModel = stringModel.extend({
|
|
create: function(json, parameters) {
|
|
var self = stringModel.create.call(this, json, parameters);
|
|
var collectionCls = Barricade.create({
|
|
'@type': String,
|
|
'@ref': {
|
|
to: function() {
|
|
return parameters.toCls;
|
|
},
|
|
needs: function() {
|
|
return parameters.neededCls;
|
|
},
|
|
getter: function(data) {
|
|
return data.needed.get(parameters.substitutedEntryID);
|
|
}
|
|
}
|
|
});
|
|
|
|
self._collection = collectionCls.create().on(
|
|
'replace', function(newValue) {
|
|
self._collection = newValue;
|
|
self._collection.on('change', function() {
|
|
self._choices = self._collection.getIDs();
|
|
self.resetValues();
|
|
});
|
|
self._collection.emit('change');
|
|
});
|
|
|
|
return self;
|
|
},
|
|
_choices: []
|
|
}, {
|
|
'@enum': function() {
|
|
if ( this._collection.isPlaceholder() ) {
|
|
this.emit('_resolveUp', this._collection);
|
|
}
|
|
return this._choices;
|
|
}
|
|
}
|
|
);
|
|
|
|
return {
|
|
string: stringModel,
|
|
text: textModel,
|
|
number: numberModel,
|
|
list: listModel,
|
|
linkedcollection: linkedCollectionModel,
|
|
dictionary: dictionaryModel,
|
|
frozendict: frozendictModel,
|
|
wildcard: wildcardMixin // use for most general type-checks
|
|
};
|
|
}
|
|
})();
|