From 106e73618a1101c28a9ea5e50fbdd4ab14317d17 Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Wed, 12 Mar 2008 22:24:33 +0000 Subject: [PATCH] Adding an args argument to OpenLayers.String.format. This lets you set context properties as functions that will be executed with the given arguments where tokens match. For styles, this means you can specify a context that contains functions that return some value based on the feature being styled. See the styles-context.html example for use. r=ahocevar (closes #1434) git-svn-id: http://svn.openlayers.org/trunk/openlayers@6512 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf --- examples/styles-context.html | 216 +++++++++++++++++++++++++++++++++++ lib/OpenLayers/BaseTypes.js | 19 ++- lib/OpenLayers/Style.js | 12 +- tests/test_BaseTypes.html | 27 ++++- 4 files changed, 263 insertions(+), 11 deletions(-) create mode 100644 examples/styles-context.html diff --git a/examples/styles-context.html b/examples/styles-context.html new file mode 100644 index 0000000000..4849cfc540 --- /dev/null +++ b/examples/styles-context.html @@ -0,0 +1,216 @@ + + + OpenLayers Vector Styles + + + + + + +

Feature Styles Example

+ +
+ +

+ Shows how to create a feature styles. +

+ +
+ +
+

Features in the northern hemisphere are styled according to their + "type" attribute. This is accomplished with a simple template that + is evaluated with the feature attributes as context.

+

Features in the sourthern hemisphere are styled according to a + combination of their attributes and non-attribute properties. This + is accomplished using an advanced template that calls functions + on the context object passed to the Style constructor.

+
+ + + + + OpenLayers Vector Styles + + + + + + +

Feature Styles Example

+ +
+ +

+ Shows how to create a feature styles. +

+ +
+ +
+

Features in the northern hemisphere are styled according to their + "type" attribute. This is accomplished with a simple template that + is evaluated with the feature attributes as context.

+

Features in the sourthern hemisphere are styled according to a + combination of their attributes and non-attribute properties. This + is accomplished using an advanced template that calls functions + on the context object passed to the Style constructor.

+
+ + diff --git a/lib/OpenLayers/BaseTypes.js b/lib/OpenLayers/BaseTypes.js index b0fdfaea93..939753efe4 100644 --- a/lib/OpenLayers/BaseTypes.js +++ b/lib/OpenLayers/BaseTypes.js @@ -106,22 +106,31 @@ OpenLayers.String = { * context - {Object} An optional object with properties corresponding * to the tokens in the format string. If no context is sent, the * window object will be used. + * args - {Array} Optional arguments to pass to any functions found in + * the context. If a context property is a function, the token + * will be replaced by the return from the function called with + * these arguments. * * Returns: * {String} A string with tokens replaced from the context object. */ - format: function(template, context) { + format: function(template, context, args) { if(!context) { context = window; } var tokens = template.split("${"); - var item, last; + var item, last, replacement; for(var i=1; i 0) { - tokens[i] = context[item.substring(0, last)] + - item.substring(++last); + if(last > 0) { + replacement = context[item.substring(0, last)]; + if(typeof replacement == "function") { + replacement = args ? + replacement.apply(null, args) : + replacement(); + } + tokens[i] = replacement + item.substring(++last); } else { tokens[i] = "${" + item; } diff --git a/lib/OpenLayers/Style.js b/lib/OpenLayers/Style.js index 40d9ac8c59..4db67448fa 100644 --- a/lib/OpenLayers/Style.js +++ b/lib/OpenLayers/Style.js @@ -196,7 +196,7 @@ OpenLayers.Style = OpenLayers.Class({ var context = this.context || feature.attributes || feature.data; for (var i in this.propertyStyles) { - style[i] = OpenLayers.Style.createLiteral(style[i], context); + style[i] = OpenLayers.Style.createLiteral(style[i], context, feature); } return style; }, @@ -315,20 +315,22 @@ OpenLayers.Style = OpenLayers.Class({ * into a Literal, taking the property values from the passed features. * * Parameters: - * value {String} value to parse. If this string contains a construct like + * value - {String} value to parse. If this string contains a construct like * "foo ${bar}", then "foo " will be taken as literal, and "${bar}" * will be replaced by the value of the "bar" attribute of the passed * feature. - * context {Object} context to take attribute values from + * context - {Object} context to take attribute values from + * feature - {OpenLayers.Feature.Vector} The feature that will be passed + * to for evaluating functions in the context. * * Returns: * {String} the parsed value. In the example of the value parameter above, the * result would be "foo valueOfBar", assuming that the passed feature has an * attribute named "bar" with the value "valueOfBar". */ -OpenLayers.Style.createLiteral = function(value, context) { +OpenLayers.Style.createLiteral = function(value, context, feature) { if (typeof value == "string" && value.indexOf("${") != -1) { - value = OpenLayers.String.format(value, context) + value = OpenLayers.String.format(value, context, [feature]); value = isNaN(value) ? value : parseFloat(value); } return value; diff --git a/tests/test_BaseTypes.html b/tests/test_BaseTypes.html index d9f071ebd7..ea56192ea2 100644 --- a/tests/test_BaseTypes.html +++ b/tests/test_BaseTypes.html @@ -89,7 +89,7 @@ "", "${ ", "${", " ${", "${${", "${}", "${${}}", " ${ ${", "}", "${${} }" ] - t.plan(4 + unchanged.length); + t.plan(6 + unchanged.length); var format = OpenLayers.String.format; @@ -114,6 +114,31 @@ var context = {bar: "foo", foo: "bar"}; t.eq(format("a ${bar} is a ${foo}", context), "a foo is a bar", "multiple properties replaced correctly"); + + // test context with properties that are functions + var context = { + bar: "church", + getDrunk: function() { + return arguments[0]; + } + }; + t.eq( + format("I go to the ${bar} to ${getDrunk}.", context, ["eat pretzels"]), + "I go to the church to eat pretzels.", + "function correctly called in context with arguments" + ); + + // test that things don't break + var context = { + meaning: function(truth) { + return truth; + } + }; + t.eq( + format("In life, truth is ${meaning}.", context), + "In life, truth is undefined.", + "still works if arguments are not supplied" + ); }