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.