I was really disappointed when I found out how poorly implemented regular expressions seem to be. I first wrote/tested the code in the FireBug console.
First fail of XPages - passing a function as the second parameter of String.replace:
var object = { firstName: 'Tommy', lastName: 'Valand' };
var template = '{lastName}, {firstName}';
template.replace( /\{(\w+)\}/g, function( item, key ){
return object[key] || '';
});
The result should be: "Valand, Tommy" The result is: ","
String.replace in Server Side JS does not accept a function as the second parameter.
Then I thought I could use String.match to pick out all the template-parts of the string:
var template = '{lastName}, {firstName}';
template.match( /\{(\w+)\}/g );
The result should be: ["{lastName}", "{firstName}"] The result is: ["{lastName}", "lastName"]
String.match in Server Side JS ignores the global modifier.
The worst part.. The above JavaScript code works with Client JavaScript in Notes, which I believe was introduced in Notes 5.0.. :\
I know the JavaScript in XPages is built on Java, but that is not an excuse. The Regular Expression engine in Java is even more powerful than the engine in JavaScript.
I've posted a bug-report in the forums (and ranted on my blog). Not sure if there is more I can do to influence IBM to fix this.. :\
If you want to do something along the lines of what I was trying to do. Here is my workaround-code:
function mapJsonToTemplate( jsonString, template ){
var jsonObject = eval( '(' + jsonString + ')' );
// In REAL JavaScript, string.replace can have a function as a second argument
// This is not possible in XPages JavaScript, so I have to get every item
// and replace them item by item, in a loop
var itemRegExp = /\{(\w+)\}/;
var result = template;
var matchArr;
while( matchArr = result.match( itemRegExp ) ){
result = result.replace( matchArr[0], jsonObject[ matchArr[1] ] );
}
return result;
}
mapJsonToTemplate( '{"firstName":"Tommy","lastName":"Valand"}', '{lastName}, {firstName}' )
-> "Valand, Tommy"
The reason for taking a string as input will be explained in my next blogpost, which should be along shortly.
7 comments:
Tommy,
this has bitten me too. I tried to use the global mod for the match function, only to discover it didn't work. Very frustrating.
Thanks for your workaround.
bit me too, ened up using @replacesubstring
Still nog working as expected in XPages, after some cursing used your work around!
Tanks
You saved my day!
JSS is supporting functions but there is a bug. (Probably in the JS to Java converting)
The problem could be solved by adding a extra set of parenthesis at the end of the Regular Expression code.
If you only got one parenthesis it leave the position for the first hit.
from your ex.
var object = { firstName: 'Tommy', lastName: 'Valand' };
var template = '{lastName}, {firstName}';
template.replace( /\{(\w+)\}()/g, function( item, key ){
return object[key] || '';
});
this return the correct answer.
Gunnar
Nice :)
How in the world did you figure this out?
I had a regular expression with several capturing groups. When adding a breakpoint inside the function I saw that the attributes to the functions had values.
But first I did try your "replaceAllFn" in
http://dontpanic82.blogspot.fi/2009/04/xpages-workarounds-for-lack-of-regular.html
but I did not manage it to work with multiple capturing groups and if the string contains multiple instance that should be replaced.
Gunnar
Post a Comment