merlin/merlin/static/merlin/js/merlin.field.models.js

280 lines
8.4 KiB
JavaScript

(function() {
'use strict';
angular.module('merlin')
.factory('merlin.field.models',
['merlin.utils', 'merlin.panel.models', '$http', function(utils, panels, $http) {
var wildcardMixin = Barricade.Blueprint.create(function() {
return this;
});
var restrictedChoicesMixin = Barricade.Blueprint.create(function() {
var self = this,
values, labels, items;
function fillItems() {
values = self.getEnumValues();
labels = self.getEnumLabels();
items = {};
values && values.forEach(function (value, index) {
items[value] = labels[index];
});
}
this.getLabel = function(value) {
if ( values === undefined ) {
fillItems();
}
return items[value];
};
this.getValues = function() {
if ( values === undefined ) {
fillItems();
}
return values;
};
this.resetValues = function() {
values = undefined;
};
this.setType('choices');
return this;
});
var modelMixin = Barricade.Blueprint.create(function(type) {
var isValid = true,
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.isAtomic = function() {
return ['number', 'string', 'text', 'choices'].indexOf(this.getType()) > -1;
};
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 ) {
restrictedChoicesMixin.call(this);
}
var autocompletionUrl = utils.getMeta(this, 'autocompletionUrl');
if ( autocompletionUrl ) {
autoCompletionMixin.call(this, autocompletionUrl);
}
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 autoCompletionMixin = Barricade.Blueprint.create(function(url) {
var self = this;
this.getSuggestions = function() { return []; };
$http.get(url).success(function(data) {
self.getSuggestions = function() {
return data;
};
});
return this;
});
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);
};
self.getValues = function() {
return self.toArray();
};
self._getContents = function() {
return self.toArray();
};
meldGroup.call(self);
return self;
}
}, {'@type': Array});
var frozendictModel = Barricade.ImmutableObject.extend({
create: function(json, parameters) {
var self = Barricade.ImmutableObject.create.call(this, json, parameters);
self.getKeys().forEach(function(key) {
utils.enhanceItemWithID(self.get(key), key);
});
modelMixin.call(self, 'frozendict');
self.getValues = function() {
return self._data;
};
self._getContents = function() {
return self.getKeys().map(function(key) {
return self.get(key);
})
};
meldGroup.call(self);
return self;
}
}, {'@type': Object});
var dictionaryModel = Barricade.MutableObject.extend({
create: function(json, parameters) {
var self = Barricade.MutableObject.create.call(this, json, parameters),
_items = [],
_elClass = self._elementClass,
baseKey = utils.getMeta(_elClass, 'baseKey') || 'key',
baseName = utils.getMeta(_elClass, 'baseName') || utils.makeTitle(baseKey);
modelMixin.call(self, 'dictionary');
function makeCacheWrapper(container, key) {
var value = container.getByID(key);
value.keyValue = function () {
if ( arguments.length ) {
value.setID(arguments[0]);
} else {
return value.getID();
}
};
return value;
}
self.add = function(newID) {
var regexp = new RegExp('(' + baseKey + ')([0-9]+)'),
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}));
_items.push(makeCacheWrapper(self, newID));
};
self.getValues = function() {
if ( !_items.length ) {
_items = self.toArray().map(function(value) {
return makeCacheWrapper(self, value.getID());
});
}
return _items;
};
self._getContents = function() {
return self.toArray();
};
self.remove = function(key) {
var pos = self.getPosByID(key);
Barricade.MutableObject.remove.call(self, pos);
_items.splice(pos, 1);
};
meldGroup.call(self);
return self;
}
}, {'@type': Object});
var directedDictionaryModel = dictionaryModel.extend({
create: function(json, parameters) {
var self = dictionaryModel.create.call(this, json, parameters);
self.setType('frozendict');
return self;
},
setSchema: function(keys) {
var self = this;
if ( keys !== undefined && keys !== null ) {
self.getIDs().forEach(function(oldKey) {
self.remove(oldKey);
});
keys.forEach(function(newKey) {
self.add(newKey);
});
}
}
}, {
'?': {'@type': String}
});
return {
string: stringModel,
text: textModel,
number: numberModel,
list: listModel,
dictionary: dictionaryModel,
frozendict: frozendictModel,
directeddictionary: directedDictionaryModel,
autocompletionmixin: autoCompletionMixin,
wildcard: wildcardMixin // use for most general type-checks
};
}])
})();