your buildurl example cannot benefit from JavaScript because it is not
constructing code.  it is constructing something to be merged into code, and
the way you've coded it below is exactly right.  you'd just merge that in
with getUrl() overrides and super exactly the way you'd think.  but for
cases where it's code, you give users a bunch of nice extensible OO tools
for constructing scripts.  that's certainly better than String, imo.


Jonathan Locke wrote:
> 
> 
> 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#a10091337
Sent from the Wicket - Dev mailing list archive at Nabble.com.

Reply via email to