From b625e9f12fe891e0fe85e4ba6aea7348de998fc2 Mon Sep 17 00:00:00 2001 From: crschmidt Date: Fri, 27 Feb 2009 00:44:20 +0000 Subject: [PATCH] Fix for "BaseTypes.String.Format does not support sub-elements", patch + tests from rdewit, r=me, (Closes #1956) git-svn-id: http://svn.openlayers.org/trunk/openlayers@8900 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf --- lib/OpenLayers/BaseTypes.js | 59 +++++++++++++++++++++++++++---------- tests/BaseTypes.html | 19 +++++++++++- 2 files changed, 61 insertions(+), 17 deletions(-) diff --git a/lib/OpenLayers/BaseTypes.js b/lib/OpenLayers/BaseTypes.js index 9660d00e0f..0b09c91054 100644 --- a/lib/OpenLayers/BaseTypes.js +++ b/lib/OpenLayers/BaseTypes.js @@ -116,25 +116,52 @@ OpenLayers.String = { if(!context) { context = window; } - var tokens = template.split("${"); - var item, last, replacement; - for(var i=1, len=tokens.length; i 0) { - replacement = context[item.substring(0, last)]; - if(typeof replacement == "function") { - replacement = args ? - replacement.apply(null, args) : - replacement(); + + // Example matching: + // str = ${foo.bar} + // match = foo.bar + var replacer = function(str, match) { + var replacement; + + // Loop through all subs. Example: ${a.b.c} + // 0 -> replacement = context[a]; + // 1 -> replacement = context[a][b]; + // 2 -> replacement = context[a][b][c]; + var subs = match.split(/\.+/); + for (var i=0; i< subs.length; i++) { + if (i == 0) { + replacement = context; } - tokens[i] = replacement + item.substring(++last); - } else { - tokens[i] = "${" + item; + + replacement = replacement[subs[i]]; } - } - return tokens.join(""); + + if(typeof replacement == "function") { + replacement = args ? + replacement.apply(null, args) : + replacement(); + } + + // If replacement is undefined, return the string 'undefined'. + // This is a workaround for a bugs in browsers not properly + // dealing with non-participating groups in regular expressions: + // http://blog.stevenlevithan.com/archives/npcg-javascript + if (typeof replacement == 'undefined') { + return 'undefined'; + } else { + return replacement; + } + }; + + return template.replace(OpenLayers.String.tokenRegEx, replacer); }, + + /** + * Property: OpenLayers.String.tokenRegEx + * Used to find tokens in a string. + * Examples: ${a}, ${a.b.c}, ${a-b}, ${5} + */ + tokenRegEx: /\${([\w.]+?)}/g, /** * Property: OpenLayers.String.numberRegEx diff --git a/tests/BaseTypes.html b/tests/BaseTypes.html index 5d6e8e2c92..7d30ea26d3 100644 --- a/tests/BaseTypes.html +++ b/tests/BaseTypes.html @@ -89,7 +89,7 @@ "", "${ ", "${", " ${", "${${", "${}", "${${}}", " ${ ${", "}", "${${} }" ] - t.plan(6 + unchanged.length); + t.plan(7 + unchanged.length); var format = OpenLayers.String.format; @@ -140,6 +140,23 @@ "still works if arguments are not supplied" ); + // test contexts where attribute values can be objects + var context = { + a: { + b: { + c: 'd', + e: function() { + return 'f'; + } + } + } + }; + t.eq( + format("${a.b.c} ${a.b.e} ${a.b.q} ${a} ${a...b...c}", context), + "d f undefined [object Object] d", + "attribute values that are objects are supported" + ); + } function test_String_isNumeric(t) {