Adding ol.Expression

This simple expression constructor will be used for symbolizer properties and the layer will generate symbolizer literals for rendering by evaluating any expressions with a feature as the this argument and feature attributes as the scope.  This allows generating labels that concatenate multiple attribute values together or displaying point symbols that are sized according to a population attribute divided by an area attribute, for example.

This implementation will not work in environments where the content security policy disallows the use of the Function constructor.  This is the case on browser extensions.  A more content-security-policy-friendly implementation would be to come up with a restricted grammar and write a lex/parser.  This is the road I started down, but this verison is far less code, and I think the security policy limitations are minor at this point.  This version will always be faster/lighter than a parser, so one is written in the future, it should only be pulled in where content security policy mandates it.
This commit is contained in:
Tim Schaub
2013-02-14 17:19:15 -07:00
parent 59a203b2b7
commit be255ed6c7
2 changed files with 121 additions and 0 deletions

43
src/ol/expression.js Normal file
View File

@@ -0,0 +1,43 @@
goog.provide('ol.Expression');
/**
* @constructor
* @param {string} source Expression to be evaluated.
*/
ol.Expression = function(source) {
/**
* @type {string}
* @private
*/
this.source_ = source;
};
/**
* Evaluate the expression and return the result.
*
* @param {Object=} opt_thisArg Object to use as this when evaluating the
* expression. If not provided, the global object will be used.
* @param {Object=} opt_scope Evaluation scope. All properties of this object
* will be available as variables when evaluating the expression. If not
* provided, the global object will be used.
* @return {*} Result of the expression.
*/
ol.Expression.prototype.evaluate = function(opt_thisArg, opt_scope) {
var thisArg = goog.isDef(opt_thisArg) ? opt_thisArg : goog.global,
scope = goog.isDef(opt_scope) ? opt_scope : goog.global,
names = [],
values = [];
for (var name in scope) {
names.push(name);
values.push(scope[name]);
}
var evaluator = new Function(names.join(','), 'return ' + this.source_);
return evaluator.apply(thisArg, values);
};