> From an outside view the difference is whether the Enclosure is added
> automatically or manually. From an implementation point of view the
> automatic approach requires quite a bit of magic / complexity.

I hope you don't aim at almost watering the whole idea ;)

The idea of auto ajax enclosure is to give the coder similar java-side
implementation for AJAX as there is for NON AJAX.

Without the current proposal, a non ajax implementor does not need to
care about enclosures when implementing on java-side. However, an ajax
implementor must do unnecessary of loops and hoops to accomplish just
the same thing.

We are trying to give the same freedom to the ajax-developer: not to
have to make boilerprate to implement eclosure behavior in ajax mode.

> As I said, just a thought.

Did you try it out, the test cases etc. and how fly it is to use ajax
enclosures with it?

**
Martin


>
>
> -Juergen
>
> On Sun, Feb 20, 2011 at 5:16 PM, Juergen Donnerstag
> <[email protected]> wrote:
>> I did a first review.
>>
>> - EnclosureHandler: A variable to increment the id postfix will not
>> work. A fresh copy of MarkupParser and all its handlers is created for
>> every markup file (page, panel, border, etc.). Your increment will
>> thus only be unique within the a single markup file. Your page however
>> may have many Panels. That wouldn't be a problem for Wicket because of
>> its hierarchy, but HTML IDs must be unique on the page.
>> Markup parsing / loading is completely decoupled from wickets
>> components hierarchy, there is no Page available. That linkage happens
>> in Resolvers. See the EnclosureResolver for an example.
>>
>> - besides that I think its poor practice to introduce a dependency on
>> Enclosure in MarkupContainer, auto-added components must be removed
>> after the render process as you otherwise keep on adding new ones and
>> your are not freeing them up. I don't understand anyway why you did
>> this change, since Enclosure don't have any state.
>>
>> - you added code to EnclosureHandler and EnclosureResolver and
>> Enclosure. Tinkering a bit with the code, I think having an
>> InlineEnclosureHandler and InlineEnclosure keeps them nicely separated
>> and thus cleaner. InlineEnclosureHandler has only very little in
>> common with EnclosureHandler and could be separate, whereas
>> InlineEnclosure is probably better derived from Enclosure.
>>
>>
>> -Juergen
>>
>> On Sun, Feb 20, 2011 at 5:51 AM, Joo Hama <[email protected]> 
>> wrote:
>>>> the problem with the tag is that it is not rendered into the markup so
>>>> cannot be targetted via ajax.
>>>>
>>>> -igor
>>>
>>>
>>> Yes, this is exactly the point. We cannot render Enclosure tags without
>>> breaking html,
>>> for example inside a <table>. If we cannot render it, we cannot target it
>>> with ajax. When we
>>> use an Enclosure as an attribute, this limitation is lifted, since we use an
>>> existing html tag,
>>> for example <tr wicket:enclosure="child:label1">, which gets naturally
>>> rendered without
>>> breaking the html. Also, the Enclosure as attribute doesn't get removed,
>>> thus it can have state.
>>> So now we have a stateful Enclosure enclosing a section of the html, and
>>> it's visibility can be toggled
>>> through ajax calls that toggle the visibility of it's designated child
>>> object.
>>>
>>> About the amount of boilerplate code to create an ajax-toggleable enclosure:
>>>
>>> HTML: (excluding closing tags)
>>> ---------------
>>> Before:
>>>   <wicket:enclosure child="enclosureContainer:toggleable">
>>>            <tr wicket:id="enclosureContainer"">
>>>  ......
>>> After:
>>>  <tr wicket:enclosure="child:toggleable">
>>>  .......
>>>
>>> Java: (Excluding toggling mechanism)
>>> ------------------
>>> Before:
>>>    WebMarkupContainer enclosureContainer = new
>>> WebMarkupContainer("enclosureContainer"){
>>>        @Override
>>>        public boolean isVisible() {
>>>            return get(toggleable).isVisible();
>>>        }
>>>    }).setOutputMarkupPlaceholderTag(true));
>>>    add(enclosureContainer);
>>> ..........
>>> After:
>>>    <nothing, all this is automatic with the enclosure as attribute>
>>> ..........
>>>
>>>
>>> - Joonas
>>>
>>>
>>> On Sun, Feb 20, 2011 at 7:35 AM, Igor Vaynberg 
>>> <[email protected]>wrote:
>>>
>>>> On Sat, Feb 19, 2011 at 2:20 PM, Juergen Donnerstag
>>>> <[email protected]> wrote:
>>>> > A couple of comments on previous posts
>>>> > - you can always assign your own wicket:id like <wicket:enclosure
>>>> > wicket:id="myEnclosure" child="label1">
>>>> > - yes, <wicket:enclosure> creates an auto component (no java code
>>>> > necessary) that is auto-added to the container which at that point in
>>>> > time gets rendered, when during the render process the markup stream
>>>> > hits the enclosure tag . And it gets automatically removed again which
>>>> > means you can not have any state with it.
>>>> >
>>>> > I looked at the patch and have a couple questions
>>>> >
>>>> > It seems you try to achieve 2 very different things:
>>>> >
>>>> > a)  "Changing the visibility of a child component in Ajax callback
>>>> > method will not affect the entire enclosure but just the child
>>>> > component itself. This is because only the child component is added to
>>>> > the AjaxRequestTarget."
>>>> >
>>>> > what is the limitation here? Enclosure checks the childComponent's
>>>> > visibility before it renders the Enclosure. At the end that's the
>>>> > whole idea of Enclosure. You never explicity change the Enclosure's
>>>> > visibility. You always (with and without ajax) change the visibility
>>>> > of the child component. Do I misunderstand something?
>>>> >
>>>> > b) you prefer a wicket:enclosure attribute over a wicket:enclosure tag
>>>> > you prefer <div wicket:enclosure="child:label1"> over
>>>> > <wicket:enclosure child="label1">
>>>> > Neither requires any java code. Neither is really longer or shorter
>>>> > than the other. Neither requires more or less boilerplate. It seems to
>>>> > me a matter of personal preference. That's up to the community what
>>>> > you like. We can have either or both. I'm personally more in favour of
>>>> > the tag, but that's of course only my opinion.
>>>>
>>>> the problem with the tag is that it is not rendered into the markup so
>>>> cannot be targetted via ajax.
>>>>
>>>> -igor
>>>>
>>>> >
>>>> > - Juergen
>>>> >
>>>> >
>>>> > On Tue, Feb 8, 2011 at 7:34 AM, Igor Vaynberg <[email protected]>
>>>> wrote:
>>>> >> i will try to look over it in the few coming days and give you some
>>>> feedback.
>>>> >>
>>>> >> -igor
>>>> >>
>>>> >> On Mon, Feb 7, 2011 at 3:43 AM, Joo Hama <[email protected]>
>>>> wrote:
>>>> >>> Thanks Igor and Jeremy,
>>>> >>>
>>>> >>> I managed to resolve these issues and committed a patch to JIRA:
>>>> >>>
>>>> >>> https://issues.apache.org/jira/browse/WICKET-3422
>>>> >>>
>>>> >>> It introduces an "inline" Enclosure defined as an attribute of a
>>>> >>> html tag, and a listener to find the right inline Enclosures at the
>>>> >>> time of Ajax request handling. It seems to work well with the existing
>>>> >>> wicket
>>>> >>> code base, and all tests are green. What do you guys think? Is it
>>>> suitable
>>>> >>> material to commit to wicket?
>>>> >>>
>>>> >>> - Joonas
>>>> >>> <https://issues.apache.org/jira/browse/WICKET-3422>
>>>> >>>
>>>> >>> On Fri, Jan 21, 2011 at 8:41 PM, Joo Hama <[email protected]
>>>> >wrote:
>>>> >>>
>>>> >>>>
>>>> >>>> The EnclosureResolver... container.autoAdd seems to be invoked only in
>>>> the
>>>> >>>> parsing
>>>> >>>> phase of the original request, whereas the onBeforeRender is invoked
>>>> during
>>>> >>>> handling
>>>> >>>> of the AjaxRequest (when the listener is attached to the
>>>> >>>> AjaxRequestTarget).
>>>> >>>>
>>>> >>>> I found out that the Enclosure is not a child of a Page, thus making
>>>> it
>>>> >>>> quite elusive
>>>> >>>> to get hold of in the onBeforeRespond event. I even attempted to
>>>> >>>> read MarkupStream,
>>>> >>>> and indeed found the tag there. (source below) However, in order to
>>>> add it
>>>> >>>> to the requestTarget, we
>>>> >>>> need to get hold of the component. I tried to read the path of the tag
>>>> in
>>>> >>>> the document
>>>> >>>> using ComponentTag.getPath(), but it was null. This is where i hit
>>>> brick
>>>> >>>> wall.
>>>> >>>>
>>>> >>>> Is it possible to get hold of the Enclosure component with only
>>>> >>>> the WicketTag from the
>>>> >>>> MarkupStream as reference? If not, i think this approach might not be
>>>> >>>> viable.
>>>> >>>>
>>>> >>>>
>>>> >>>> // Override of the application class method newAjaxRequestTarget,
>>>> trying to
>>>> >>>> find enclosures that have
>>>> >>>> // the child id of a component
>>>> >>>> // in the ajaxTarget:
>>>> >>>> //-----------------------
>>>> >>>> @Override
>>>> >>>> public AjaxRequestTarget newAjaxRequestTarget(Page page) {
>>>> >>>>     AjaxRequestTarget target = super.newAjaxRequestTarget(page);
>>>> >>>>     target.addListener(new AjaxRequestTarget.IListener() {
>>>> >>>>
>>>> >>>>         public void onBeforeRespond(Map<String, Component> map,
>>>> >>>>  AjaxRequestTarget target) { List<String> ids = new
>>>> ArrayList<String>();
>>>> >>>> Page page = null; // first read all the component id:s from the target
>>>> for
>>>> >>>> (Component component : map.values()) { page = component.getPage();
>>>> >>>> ids.add(component.getId()); } // then traverse the markupStream to
>>>> find
>>>> >>>> enclosureTags if (page != null) { MarkupStream stream =
>>>> >>>> page.getMarkupStream(); stream.setCurrentIndex(0); while
>>>> (stream.hasMore())
>>>> >>>> { stream.skipRawMarkup(); if (stream.hasMore()) { WicketTag tag = new
>>>> >>>> WicketTag(stream.getTag()); if (tag.isEnclosureTag()) { // Try to
>>>> match the
>>>> >>>> enclosureTag:s child id to the ids in the target String childId =
>>>> >>>> tag.getAttribute("child"); if (childId != null) { String[] parts =
>>>> >>>> childId.split(":"); childId = parts[parts.length - 1]; for (String id
>>>> : ids)
>>>> >>>> { if (id.equals(childId)) { System.err .println("Found enclosure " +
>>>> >>>> tag.getId() + " at path:" + tag.getPath() + ", who's child is targeted
>>>> Id="
>>>> >>>> + childId); } } } } stream.next(); } } } }
>>>> >>>> public void onAfterRespond(Map<String, Component> map,
>>>> IJavascriptResponse
>>>> >>>> response) { System.err.println("onAfterRespond"); } }); return target;
>>>> }
>>>> >>>> //-------------
>>>> >>>>
>>>> >>>>
>>>> >>>> On Fri, Jan 21, 2011 at 3:58 PM, Martin Makundi <
>>>> >>>> [email protected]> wrote:
>>>> >>>>
>>>> >>>>> Hi!
>>>> >>>>>
>>>> >>>>> EnclosureResolver....container.autoAdd is invoked at render phase?
>>>> >>>>> Would it be necessary to hook into a different event (instead of
>>>> >>>>> onBeforeRender) or could it be pre-sniffed at onBeforeRender?
>>>> >>>>>
>>>> >>>>> **
>>>> >>>>> Martin
>>>> >>>>>
>>>> >>>>> 2011/1/21 Joo Hama <[email protected]>:
>>>> >>>>> > I tested this idea by adding the code below to my web application
>>>> >>>>> > object. Problem was though,
>>>> >>>>> > that when viewing the variables in debugger, the enclosure object
>>>> didn't
>>>> >>>>> > seem to be included in
>>>> >>>>> > the tree of the parent objects. It was as if the enclosure was
>>>> invisible
>>>> >>>>> to
>>>> >>>>> > them. Perhaps because
>>>> >>>>> > Enclosure is a transparent resolver?
>>>> >>>>> >
>>>> >>>>> > object tree in my application:
>>>> >>>>> >
>>>> >>>>> > - page
>>>> >>>>> >  - enclosure
>>>> >>>>> >     - div (the parent of this was shown to be page, not the
>>>> enclosure)
>>>> >>>>> >
>>>> >>>>> >
>>>> >>>>> > Code:
>>>> >>>>> > //-----------------------------
>>>> >>>>> > @Override public AjaxRequestTarget newAjaxRequestTarget(Page page)
>>>> {
>>>> >>>>> > AjaxRequestTarget target = super.newAjaxRequestTarget(page);
>>>> >>>>> > target.addListener(new AjaxRequestTarget.IListener() { public void
>>>> >>>>> > onBeforeRespond(Map<String, Component> map, AjaxRequestTarget
>>>> target) {
>>>> >>>>> > for(Component component : map.values()) { Enclosure parentEnclosure
>>>> =
>>>> >>>>> > component.findParent(Enclosure.class); if (parentEnclosure != null)
>>>> {
>>>> >>>>> > Enclosure topParent = new Enclosure("DUMMY", "DUMMY"); while
>>>> (topParent
>>>> >>>>> !=
>>>> >>>>> > null) { topParent = parentEnclosure.findParent(Enclosure.class); if
>>>> >>>>> > (topParent != null) { parentEnclosure = topParent; } }
>>>> >>>>> > target.addComponent(parentEnclosure); } } } public void
>>>> >>>>> > onAfterRespond(Map<String, Component> map, IJavascriptResponse
>>>> response)
>>>> >>>>> {}
>>>> >>>>> > }); return target; };
>>>> >>>>> > //-----------------------
>>>> >>>>> >
>>>> >>>>> >
>>>> >>>>> > On Fri, Jan 21, 2011 at 3:07 AM, Jeremy Thomerson <
>>>> >>>>> [email protected]
>>>> >>>>> >> wrote:
>>>> >>>>> >
>>>> >>>>> >> On Thu, Jan 20, 2011 at 1:51 PM, Igor Vaynberg <
>>>> >>>>> [email protected]
>>>> >>>>> >> >wrote:
>>>> >>>>> >>
>>>> >>>>> >> > interesting idea. i think this would require a bit of a trick.
>>>> >>>>> >> >
>>>> >>>>> >> > a) modify enclosure tag handler to accept an attribute instead
>>>> of a
>>>> >>>>> tag
>>>> >>>>> >> > b) modify enclosure tag handler to add a bit of metadata to the
>>>> >>>>> >> > component marking that it belongs to an enclosure
>>>> >>>>> >> > c) add a ajaxrequesttarget.listener to the request target that
>>>> checks
>>>> >>>>> >> > for this bit of metadata and adds the enclosure container to the
>>>> ajax
>>>> >>>>> >> > request target.
>>>> >>>>> >> >
>>>> >>>>> >> > not sure how feasible this all is because the enclosure
>>>> container is
>>>> >>>>> >> > an auto component. but, you are welcome to tinker around.
>>>> >>>>> >> >
>>>> >>>>> >> > -igor
>>>> >>>>> >>
>>>> >>>>> >>
>>>> >>>>> >> I, too, like the idea.  Couldn't it be simpler?  Couldn't he:
>>>> >>>>> >>
>>>> >>>>> >> 1: Override newAjaxRequestTarget in WebApplication
>>>> >>>>> >> 2: When he creates an ART, add a listener to it.
>>>> >>>>> >> 3: In the listener, in onBeforeRespond, do this:
>>>> >>>>> >>
>>>> >>>>> >> for(Component component : map.values()) {
>>>> >>>>> >>    Enclosure parentEnclosure =
>>>> component.findParent(Enclosure.class);
>>>> >>>>> >>    while (parentEnclosure != null) {
>>>> >>>>> >>        Enclosure topParent =
>>>> >>>>> parentEnclosure.findParent(Enclosure.class);
>>>> >>>>> >>        if (topParent != null) {
>>>> >>>>> >>            parentEnclosure = topParent;
>>>> >>>>> >>        }
>>>> >>>>> >>    }
>>>> >>>>> >>    if (parentEnclosure != null) {
>>>> >>>>> >>        addComponent(parentEnclosure);
>>>> >>>>> >>    }
>>>> >>>>> >> }
>>>> >>>>> >>
>>>> >>>>> >>
>>>> >>>>> >>
>>>> >>>>> >> --
>>>> >>>>> >> Jeremy Thomerson
>>>> >>>>> >> http://wickettraining.com
>>>> >>>>> >> *Need a CMS for Wicket?  Use Brix! http://brixcms.org*
>>>> >>>>> >>
>>>> >>>>> >
>>>> >>>>>
>>>> >>>>
>>>> >>>>
>>>> >>>
>>>> >>
>>>> >
>>>>
>>>
>>
>

Reply via email to