Option name | Type | Description |
---|---|---|
model | Model | Model instance that ModelPath gives access to. |
accessPath | String | string that defines path to access model. Path string consists of parts to define either property access ( |
arguments | List | additional arguments of this method can be used to create interpolated paths. E.g. |
return | ModelPath |
milo.Model.Path
ModelPath object that allows access to any point inside Model as defined by accessPath
function ModelPath(model, path) { // ,... - additional arguments for interpolation
// check(model, Model);
check(path, String);
// `modelPath` will be returned by constructor instead of `this`. `modelPath`
// (`modelPath_path` function) should also return a ModelPath object with "synthesized" methods
// to get/set model properties, to subscribe to property changes, etc.
// Additional arguments of modelPath can be used in the path using interpolation - see ModelPath below.
var modelPath = function modelPath_path(accessPath) { // , ... arguments that will be interpolated
return ModelPath$path.apply(modelPath, arguments);
};
modelPath.__proto__ = ModelPath.prototype;
_.defineProperties(modelPath, {
_model: model,
_path: path,
_args: _.slice(arguments, 1), // path will be the first element of this array
_options: model._options
});
// parse access path
var parsedPath = pathUtils.parseAccessPath(path);
// compute access path string
_.defineProperty(modelPath, '_accessPath', interpolateAccessPath(parsedPath, modelPath._args));
if (modelPath._options.reactive !== false) {
// messenger fails on "*" subscriptions
modelPath._prepareMessenger();
// subscribe to "changedata" message to enable reactive connections
modelPath.onSync('changedata', changeDataHandler);
}
// compiling getter and setter
var methods = synthesize(path, parsedPath);
// adding methods to model path
_.defineProperties(modelPath, methods);
Object.freeze(modelPath);
return modelPath;
}
ModelPath.prototype.__proto__ = ModelPath.__proto__;
Option name | Type | Description |
---|---|---|
parsedPath | Array | parsed path - array of path nodes |
args | Array | path interpolation arguments, args[0] is path itself |
return | String |
Interpolates path elements to compute real path
function interpolateAccessPath(parsedPath, args) {
return parsedPath.reduce(function(accessPathStr, currNode, index) {
var interpolate = currNode.interpolate;
return accessPathStr +
(interpolate
? (currNode.syntax == 'array'
? '[' + args[interpolate] + ']'
: '.' + args[interpolate])
: currNode.property);
}, '');
}
_.extendProto(ModelPath, {
path: ModelPath$path,
len: ModelPath$len,
push: ModelPath$push,
pop: ModelPath$pop,
unshift: ModelPath$unshift,
shift: ModelPath$shift,
_prepareMessenger: _prepareMessenger,
_getDefinition: _getDefinition,
destroy: ModelPath$destroy
});
_.extend(ModelPath, {
_createFromDefinition: _createFromDefinition
})
Expose Messenger methods on Facet prototype
var MESSENGER_PROPERTY = '_messenger';
Messenger.useWith(ModelPath, MESSENGER_PROPERTY, Messenger.defaultMethods);
Option name | Type | Description |
---|---|---|
accessPath | String | string that defines path to access model. Path string consists of parts to define either property access ( |
arguments | List | additional arguments of this method can be used to create interpolated paths. E.g. |
return | ModelPath |
ModelPath instance method
Gives access to path inside ModelPath. Method works similarly to path method of model, using relative paths.
function ModelPath$path(accessPath) { // , ... arguments that will be interpolated
if (! accessPath) return this;
var thisPathArgsCount = this._args.length - 1;
if (thisPathArgsCount > 0) {// this path has interpolated arguments too
accessPath = accessPath.replace(/\$[1-9][0-9]*/g, function(str) {
return '$' + (+str.slice(1) + thisPathArgsCount);
});
}
var newPath = this._path + accessPath;
// this._model is added in front of all arguments as the first parameter
// of ModelPath constructor
var args = [this._model, newPath]
.concat(this._args.slice(1)) // remove old path from _args, as it is 1 based
.concat(_.slice(arguments, 1)); // add new interpolation arguments
// calling ModelPath constructor with new and the list of arguments: this (model), accessPath, ...
return _.newApply(ModelPath, args);
}
ModelPath and Model instance method
Returns length property and sets it to 0 if it wasn't set.
function ModelPath$len() {
return this.path('.length').get() || 0;
}
Option name | Type | Description |
---|---|---|
arguments | List | list of items that will be added to array (pseudo array) |
return | Integer |
ModelPath and Model instance method
Adds items to the end of array (or pseudo-array). Returns new length.
function ModelPath$push() { // arguments
var length = this.len();
var newLength = length + arguments.length;
_.splice(arguments, 0, 0, length, 0);
this.splice.apply(this, arguments);
return newLength;
}
ModelPath and Model instance method
Removes item from the end of array (or pseudo-array). Returns this item.
function ModelPath$pop() {
return this.splice(this.len() - 1, 1)[0];
}
Option name | Type | Description |
---|---|---|
arguments | List | items to be inserted in the beginning of array |
return | Integer |
ModelPath and Model instance method
Inserts items to the beginning of the array. Returns new length.
function ModelPath$unshift() { // arguments
var length = this.len();
length += arguments.length;
_.splice(arguments, 0, 0, 0, 0);
this.splice.apply(this, arguments);
return length;
}
ModelPath and Model instance method
Removes the item from the beginning of array (or pseudo-array). Returns this item.
function ModelPath$shift() { // arguments
return this.splice(0, 1)[0];
}
ModelPath instance method
Initializes ModelPath mesenger with Model's messenger as its source (MessengerMessageSource) and ModelPathMsgAPI as MessengerAPI
function _prepareMessenger() {
var mPathAPI = new ModelPathMsgAPI(this._accessPath);
// create MessengerMessageSource connected to Model's messenger
var modelMessageSource = new MessengerMessageSource(this, undefined, mPathAPI, this._model);
// create messenger with model passed as hostObject (default message dispatch context)
// and without proxying methods (we don't want to proxy them to Model)
var mPathMessenger = new Messenger(this, undefined, modelMessageSource);
// store messenger on ModelPath instance
_.defineProperty(this, MESSENGER_PROPERTY, mPathMessenger);
}
Returns the object allowing to recreate model path
function _getDefinition() {
return {
model: this._model,
path: this._path,
args: this._args
};
}
Option name | Type | Description |
---|---|---|
definition | Object | |
return | ModelPath |
Class method
Creates modelPath object from definition created by _getDefinition
function _createFromDefinition(definition) {
check(definition, {
model: Function, // Model
path: String,
args: Array
});
var m = definition.model;
return m.apply(m, definition.args);
}
function ModelPath$destroy() {
this[MESSENGER_PROPERTY].destroy();
}