devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
190 lines (152 loc) • 5.57 kB
JavaScript
var errors = require("../errors"),
Class = require("../class"),
objectUtils = require("./object"),
typeUtils = require("./type"),
each = require("./iterator").each,
variableWrapper = require("./variable_wrapper"),
unwrapVariable = variableWrapper.unwrap,
isWrapped = variableWrapper.isWrapped,
assign = variableWrapper.assign;
var bracketsToDots = function bracketsToDots(expr) {
return expr.replace(/\[/g, ".").replace(/\]/g, "");
};
var readPropValue = function readPropValue(obj, propName, options) {
options = options || {};
if (propName === "this") {
return unwrap(obj, options);
}
return unwrap(obj[propName], options);
};
var assignPropValue = function assignPropValue(obj, propName, value, options) {
if (propName === "this") {
throw new errors.Error("E4016");
}
var propValue = obj[propName];
if (options.unwrapObservables && isWrapped(propValue)) {
assign(propValue, value);
} else {
obj[propName] = value;
}
};
var prepareOptions = function prepareOptions(options) {
options = options || {};
options.unwrapObservables = options.unwrapObservables !== undefined ? options.unwrapObservables : true;
return options;
};
var unwrap = function unwrap(value, options) {
return options.unwrapObservables ? unwrapVariable(value) : value;
};
var compileGetter = function compileGetter(expr) {
if (arguments.length > 1) {
expr = [].slice.call(arguments);
}
if (!expr || expr === "this") {
return function (obj) {
return obj;
};
}
if (typeof expr === "string") {
expr = bracketsToDots(expr);
var path = expr.split(".");
return function (obj, options) {
options = prepareOptions(options);
var functionAsIs = options.functionsAsIs,
current = unwrap(obj, options);
for (var i = 0; i < path.length; i++) {
if (!current) break;
var next = unwrap(current[path[i]], options);
if (!functionAsIs && typeUtils.isFunction(next)) {
next = next.call(current);
}
current = next;
}
return current;
};
}
if (Array.isArray(expr)) {
return combineGetters(expr);
}
if (typeUtils.isFunction(expr)) {
return expr;
}
};
var combineGetters = function combineGetters(getters) {
var compiledGetters = {};
for (var i = 0, l = getters.length; i < l; i++) {
var getter = getters[i];
compiledGetters[getter] = compileGetter(getter);
}
return function (obj, options) {
var result;
each(compiledGetters, function (name) {
var value = this(obj, options),
current,
path,
last,
i;
if (value === undefined) {
return;
}
current = result || (result = {});
path = name.split(".");
last = path.length - 1;
for (i = 0; i < last; i++) {
current = current[path[i]] = {};
}
current[path[i]] = value;
});
return result;
};
};
var ensurePropValueDefined = function ensurePropValueDefined(obj, propName, value, options) {
if (typeUtils.isDefined(value)) {
return value;
}
var newValue = {};
assignPropValue(obj, propName, newValue, options);
return newValue;
};
var compileSetter = function compileSetter(expr) {
expr = bracketsToDots(expr || "this").split(".");
var lastLevelIndex = expr.length - 1;
return function (obj, value, options) {
options = prepareOptions(options);
var currentValue = unwrap(obj, options);
expr.forEach(function (propertyName, levelIndex) {
var propertyValue = readPropValue(currentValue, propertyName, options),
isPropertyFunc = !options.functionsAsIs && typeUtils.isFunction(propertyValue) && !isWrapped(propertyValue);
if (levelIndex === lastLevelIndex) {
if (options.merge && typeUtils.isPlainObject(value) && (!typeUtils.isDefined(propertyValue) || typeUtils.isPlainObject(propertyValue))) {
propertyValue = ensurePropValueDefined(currentValue, propertyName, propertyValue, options);
objectUtils.deepExtendArraySafe(propertyValue, value, false, true);
} else if (isPropertyFunc) {
currentValue[propertyName](value);
} else {
assignPropValue(currentValue, propertyName, value, options);
}
} else {
propertyValue = ensurePropValueDefined(currentValue, propertyName, propertyValue, options);
if (isPropertyFunc) {
propertyValue = propertyValue.call(currentValue);
}
currentValue = propertyValue;
}
});
};
};
var toComparable = function toComparable(value, caseSensitive) {
if (value instanceof Date) {
return value.getTime();
}
if (value && value instanceof Class && value.valueOf) {
return value.valueOf();
}
if (!caseSensitive && typeof value === "string") {
return value.toLowerCase();
}
return value;
};
exports.compileGetter = compileGetter;
exports.compileSetter = compileSetter;
exports.toComparable = toComparable;
;