don't forget that a javascript decorator isa JavaScript, so you can nest them arbitrarily:
public static class ThrottlingDecorator extends JavaScript { <<<<<<<< } JavaScript code = new WhateverDecorator(new ThrottlingDecorator(script)); i'm still not getting what you think is missing from this solution. it could be that i don't understand the requirements fully, but this solution i'm proposing definitely decorates to any number of levels you want. igor.vaynberg wrote: > > im not getting the warm and fuzzy about this. i want to, but im not. > > take our base query which has the similar success and failure points as my > example. in order to facilitate those you still need the generic > ajaxcalldecorator design because those placeholders are "inherited" across > all layers, and JavaScript doesnt support this. > > further what you have done is design a hierarchy where each layer builds > on > the previous. but that means each layer has to know the previous layers' > class so it can override the proper places. this is not true in our ajax > support. we need to be able to decorate things generically. > > like what you have done today - add a parameter to the back of the url. > well, maybe someone after you wants to do the same. and maybe someone > after > that as well. so it somehow needs to be generic, and i think something > like > > charsequence buildurl() { > return super.buildurl()+"&myparam=foo"; > } > > is the only way to do that unfortunately. i dont see how JavaScript will > make that easier. > > maybe im just entirely missing the point. > > -igor > > > On 4/19/07, Jonathan Locke <[EMAIL PROTECTED]> wrote: >> >> >> >> oops i forgot the new virtual: >> >> class abstract CucumberQuery >> { >> JavaScript getQuery() { return new JavaScript("cucumbers; ${middle}; >> moreCucumbers").merge(getMiddle()); } >> >> protected abstract Javascript getMiddle(); >> } >> >> >> Jonathan Locke wrote: >> > >> > >> > yeah, it's a little tricky, but i think the inheritance hierarchy can >> > provide the levels you're looking for (sort of as it does now) with >> > overrides and calls to super. i'm not sure exactly what you are asking >> me >> > to do, but the code might look like this (if i understand you right): >> > >> > class QueryGoogle >> > { >> > JavaScript getScript() >> > { >> > final JavaScript script = new JavaScript("function >> > wget( >> http://www.google.com/q=${query},function(){${success}},function(){${failure}} >> "); >> > return script.merge("query", getQuery(), "success", >> getSuccess(), >> > "failure", getFailure()); >> > } >> > >> > protected abstract JavaScript getQuery(); >> > protected JavaScript getSuccess() { return JavaScript.EMPTY; } >> > protected JavaScript getFailure() { return JavaScript.EMPTY; } >> > } >> > >> > class CucumberQuery >> > { >> > JavaScript getQuery() { return new JavaScript("cucumbers"); } >> > } >> > >> > class ThrottlingCucumberQuery extends CucumberQuery >> > { >> > JavaScript getQuery() { return new >> > ThrottlingDecorator(super.getQuery()); } >> > } >> > >> > class NoTomatoAndAlertCucumberQuery extends CucumberQuery >> > { >> > JavaScript noTomatoes = new JavaScript("..."); >> > JavaScript alert = new JavaScript("..."); >> > JavaScript getQuery() { return >> > super.getQuery().append(noTomatoes).append(alert); } >> > } >> > >> > Of course, if the cucumber script supports some kind of merging, it >> would >> > have to provide insertion points, like: >> > >> > class CucumberQuery >> > { >> > JavaScript getQuery() { return new JavaScript("cucumbers; >> ${middle}; >> > moreCucumbers"); } >> > } >> > >> > >> > igor.vaynberg wrote: >> >> >> >> so you got single level layering >> >> >> >> but what about multi level? >> >> >> >> lets say our default ajax behavior returns this: >> >> >> >> JavaScript code = new JavaScript( >> >> "function >> >> wget( >> http://www.google.com/q=${query},function(){${success}},function(){${failure}} >> "); >> >> >> >> now something down the road wants to search google for cucumbers >> >> >> >> so it does >> >> >> >> return code.merge("query","cucumbers"); >> >> >> >> something later down the road wants to exclude tomatoes from the >> search >> >> results, and also add an alert on failure, but since the previous >> script >> >> lost all the placeholders how would that work? i mean its really use >> it >> >> or >> >> lose it. >> >> >> >> unless the previous script that added cucumbers now provides its own >> >> placeholders for all the previous placeholders, but these need to be >> >> factored into functions or some such. >> >> >> >> could you show me what that would look like with your code? >> >> >> >> so... >> >> >> >> JavaScript code = new JavaScript( >> >> "function >> >> wget( >> http://www.google.com/q=${query},function(){${success}},function(){${failure}} >> "); >> >> >> >> one layer adds cucumbers to the query >> >> >> >> the next layer excludes tomatoes and adds an alert on failure >> >> >> >> -igor >> >> >> >> >> >> On 4/19/07, Jonathan Locke <[EMAIL PROTECTED]> wrote: >> >>> >> >>> >> >>> >> >>> A throttling decorator would look like this: >> >>> >> >>> public static class ThrottlingDecorator extends JavaScript { >> >>> >> >>> private static final JavaScript THROTTLER = new JavaScript( >> >>> "wicketThrottler.throttle('${id}', ${milliseconds}, >> >>> ${function});"); >> >>> >> >>> public ThrottlingDecorator(final String id, >> >>> final Duration maxFrequency, final JavaScript script) >> { >> >>> super(THROTTLER.merge("id", id, "milliseconds", >> maxFrequency >> >>> .getMilliseconds(), "function", script.function >> ())); >> >>> } >> >>> } >> >>> >> >>> and usage of that would be: >> >>> >> >>> code = new ThrottlingDecorator("id", Duration.ONE_SECOND, >> code); >> >>> >> >>> >> >>> Jonathan Locke wrote: >> >>> > >> >>> > Something like class below (although perhaps more efficient) could >> >>> help >> >>> us >> >>> > to decorate and merge javascript in our AJAX code. Because code >> >>> merges >> >>> > only occur one layer at a time, it's as good as an AST for our >> simple >> >>> > purposes (we don't need to globally refactor JavaScript, for >> example, >> >>> only >> >>> > combine it neatly), but much easier to use. I personally would >> have >> >>> no >> >>> > problem breaking the API to make this better, but we could also do >> >>> this >> >>> > with 100% backwards compat by simply having things that need >> >>> JavaScript >> >>> > make a call to a getWhateverJavaScript() method first and if that >> >>> returns >> >>> > null (in the default impl), it could proceed to do what it does >> now. >> >>> So >> >>> > basically if you wanted to assemble your script this new way, you >> >>> could >> >>> > override these new methods and the old stuff would be >> >>> bypassed. Feedback? >> >>> > >> >>> > Jonathan >> >>> > >> >>> > --- >> >>> > >> >>> > package thoof.util.javascript; >> >>> > >> >>> > import java.io.IOException; >> >>> > import java.io.InputStream; >> >>> > import java.util.Collections; >> >>> > import java.util.HashMap; >> >>> > import java.util.Map; >> >>> > import java.util.regex.Pattern; >> >>> > >> >>> > import org.apache.wicket.util.io.Streams; >> >>> > import >> >>> org.apache.wicket.util.string.interpolator.MapVariableInterpolator; >> >>> > >> >>> > public class JavaScript { >> >>> > >> >>> > private final String script; >> >>> > >> >>> > private static final Pattern UNINTERPOLATED_VARIABLES = Pattern >> >>> > .compile("\\s*\\$\\{\\w+\\}\\s*"); >> >>> > >> >>> > public JavaScript(final String script) { >> >>> > this.script = script; >> >>> > } >> >>> > >> >>> > public static JavaScript load(final Class<?> type, final String >> >>> > resourceName) { >> >>> > return load(type.getResourceAsStream(resourceName)); >> >>> > } >> >>> > >> >>> > public static JavaScript load(final InputStream in) { >> >>> > try { >> >>> > return new JavaScript(Streams.readString(in)); >> >>> > } catch (final IOException e) { >> >>> > throw new IllegalStateException("Cannot load email >> >>> template", >> >>> > e); >> >>> > } >> >>> > } >> >>> > >> >>> > public final JavaScript merge(final Map<String, Object> map) { >> >>> > final String mergedScript = new >> >>> > MapVariableInterpolator(this.script, >> >>> > map).toString(); >> >>> > return new >> >>> > JavaScript(UNINTERPOLATED_VARIABLES.matcher(mergedScript) >> >>> > .replaceAll(" ")); >> >>> > } >> >>> > >> >>> > public final JavaScript merge(final Object... args) { >> >>> > if (args.length % 2 != 0) { >> >>> > throw new IllegalArgumentException( >> >>> > "Invalid interpolation arguments"); >> >>> > } >> >>> > final Map<String, Object> map = new HashMap<String, >> Object>(); >> >>> > for (int i = 0; i < args.length; i += 2) { >> >>> > if (args[i] instanceof String) { >> >>> > map.put((String) args[i], args[i + 1]); >> >>> > } else { >> >>> > throw new IllegalArgumentException( >> >>> > "Invalid interpolation arguments"); >> >>> > } >> >>> > } >> >>> > return merge(map); >> >>> > } >> >>> > >> >>> > public final JavaScript prepend(final JavaScript script) { >> >>> > return new JavaScript(script + ";" + this.script); >> >>> > } >> >>> > >> >>> > public final JavaScript append(final JavaScript script) { >> >>> > return new JavaScript(this.script + ";" + script); >> >>> > } >> >>> > >> >>> > public final JavaScript function(final String functionName) { >> >>> > return new JavaScript("var " + functionName + " = function >> { >> " >> >>> + >> >>> > script >> >>> > + "};"); >> >>> > } >> >>> > >> >>> > @Override >> >>> > public String toString() { >> >>> > return MapVariableInterpolator.interpolate(script, >> >>> > Collections.EMPTY_MAP); >> >>> > } >> >>> > >> >>> > public static void main(final String arguments[]) { >> >>> > JavaScript code = new JavaScript("var x = 10 + 3"); >> >>> > System.out.println("" + code.toString()); >> >>> > code = code.prepend(new JavaScript("a + b")); >> >>> > System.out.println("" + code.toString()); >> >>> > code = code.append(new JavaScript("c + d")); >> >>> > System.out.println("" + code.toString()); >> >>> > code = code.function("callback"); >> >>> > System.out.println("" + code.toString()); >> >>> > JavaScript ajax = new JavaScript( >> >>> > "var wcall; ${beforeCallback} wcall = >> >>> > wicketAjaxGet('${url}', function() { ${success} }, function() { >> >>> ${failure} >> >>> > }); ${afterCallback} return !wcall;);"); >> >>> > code = ajax.merge("url", "/abc/def", "beforeCallback", >> code, >> >>> > "afterCallback", "a = b + c + d"); >> >>> > System.out.println("" + code.toString()); >> >>> > } >> >>> > } >> >>> > >> >>> > >> >>> >> >>> -- >> >>> View this message in context: >> >>> http://www.nabble.com/JavaScript-object-tf3610605.html#a10090957 >> >>> Sent from the Wicket - Dev mailing list archive at Nabble.com. >> >>> >> >>> >> >> >> >> >> > >> > >> >> -- >> View this message in context: >> http://www.nabble.com/JavaScript-object-tf3610605.html#a10091122 >> Sent from the Wicket - Dev mailing list archive at Nabble.com. >> >> > > -- View this message in context: http://www.nabble.com/JavaScript-object-tf3610605.html#a10091318 Sent from the Wicket - Dev mailing list archive at Nabble.com.