agiletortoise:
Right now, the Servoy method editor blocks the use of the “function” keyword (even in a literal string!).
True. However, the method editor does not block the use of the “Function” keyword. So…define your function using the new Function constructor. A decent definition of how it is used may be found here, about half-way down the page.
So, following is a simple add function example.
//adding
var add=new Function('a','b','return a+b')
application.output(add(8,3)) //returns 11
How about we create a function that is used in the definition of another function?
//any arithmetic operation
var compute=new Function('myOperator','return new Function("a", "b", "return a" + myOperator + "b")')
var multiply=compute('*')
var divide=compute('/')
var subtract=compute('-')
application.output(multiply(8,3)) //returns 24
application.output(divide(8,4)) //returns 2
application.output(subtract(8,3)) //returns 5
And now, what I read as your original need, prototyping. We’ll extend Array’s default functionality by writing a numeric sort funtion.
//prototyping any (established) object
Array.prototype.sortNum = new Function('return this.sort(new Function ("a","b","return a-b"))')
var tmp = [5,9,12,18,56,1,10,42,30,7,97,53,33,35,27]
tmp = tmp.sort() // returns alphabetical sort: 1,10,12,18,27,30,33,35,42,5,53,56,7,9,97
tmp = tmp.sortNum() // returns numerical sort: 1,5,7,9,10,12,18,27,30,33,35,42,53,56,97
A few considerations:
- Since the actual body of the function is essentially a string (contained within quotes), if your body includes quotes, you need to be creative in stringing together your code in such a way that there is only one type of quote used in each substring, with the other type surrounding it. For example,
var copyStyles = function(destDoc, sourceDoc)
{
var links = sourceDoc.getElementsByTagName('link');
for(var i = 0; i < links.length; i++)
if(links[i].rel.toLowerCase() == 'stylesheet')
destDoc.write('<link type="text/css" rel="stylesheet" href="' + links[i].href + '"></link>');
}
turns into
var copyStyles = new Function('destDoc', 'sourceDoc',
"var links = sourceDoc.getElementsByTagName('link');" +
"for(var i = 0; i < links.length; i++)" +
"if(links[i].rel.toLowerCase() == 'stylesheet')" +
"destDoc.write(" +
"'<link type=" +
'"text/css" rel="stylesheet" href="' +
"' + links[i].href + '" +
'">' +
"</link>');"
)
- Functions defined using the constructor are generally compiled when invoked, which may lead to slower than optimal performance. Although I’m not sure how Rhino handles this.
- Servoy clearly went out of their way to disable our abilitiy to use functions. Not that that is necessarily reason enough not to use them, it is just a ‘warning’.
- When prototyping, your additions to established objects are similar to globals in that they are persistent until you enter layout mode, quit servoy, etc.