You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@wicket.apache.org by Joo Hama <jo...@gmail.com> on 2011/02/07 12:43:35 UTC

Re: How to streamline ajax page region toggle

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 <jo...@gmail.com>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 <
> martin.makundi@koodaripalvelut.com> 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 <jo...@gmail.com>:
>> > 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 <
>> jeremy@wickettraining.com
>> >> wrote:
>> >
>> >> On Thu, Jan 20, 2011 at 1:51 PM, Igor Vaynberg <
>> igor.vaynberg@gmail.com
>> >> >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*
>> >>
>> >
>>
>
>

Re: How to streamline ajax page region toggle

Posted by Martin Makundi <ma...@koodaripalvelut.com>.
> 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
> <ju...@gmail.com> 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 <jo...@gmail.com> 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 <ig...@gmail.com>wrote:
>>>
>>>> On Sat, Feb 19, 2011 at 2:20 PM, Juergen Donnerstag
>>>> <ju...@gmail.com> 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 <ig...@gmail.com>
>>>> 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 <jo...@gmail.com>
>>>> 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 <joonas.hamalainen@gmail.com
>>>> >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 <
>>>> >>>> martin.makundi@koodaripalvelut.com> 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 <jo...@gmail.com>:
>>>> >>>>> > 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 <
>>>> >>>>> jeremy@wickettraining.com
>>>> >>>>> >> wrote:
>>>> >>>>> >
>>>> >>>>> >> On Thu, Jan 20, 2011 at 1:51 PM, Igor Vaynberg <
>>>> >>>>> igor.vaynberg@gmail.com
>>>> >>>>> >> >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*
>>>> >>>>> >>
>>>> >>>>> >
>>>> >>>>>
>>>> >>>>
>>>> >>>>
>>>> >>>
>>>> >>
>>>> >
>>>>
>>>
>>
>

Re: How to streamline ajax page region toggle

Posted by Juergen Donnerstag <ju...@gmail.com>.
IMO it's quite a bit of (partially complex) code to achieve the objective.

Just a thought (I've not implemented/tested it). It'll not lead to the
very same result, but may be a less complex implementation =>
tradeoff. The basic idea: provided the child id is not necessarily
something the html designer needs to know/assign, but it would be ok
to assign it in Java. With the additional benefit that an object
reference to the child can be used instead of a String (avoid rename
issues). You'd simply need to add a wicket:id to <tr> (instead of
wicket:enclosure) and to manually add a special component in Java (not
needed in your approach). A component similar to Enclosure in
behavior, but because it'll be added to the hierarchy with proper
child relationships (different than auto components), its
implementation would be much simpler (see EnclosureContainer in 1.5).
setOutputMarkupId() could be set automatically in the pre-render
phase. Finding the child enclosure would be as simple as walking up
the hierarchy - no magic at all. And different than the ART.Listener
I'd prefer an interface with a single callback which is invoked upon
adding a component (child) to the ART. ART would check the child and
all its parents for the interface to allow the Enclosure to add itself
as well.

>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.

As I said, just a thought.

-Juergen

On Sun, Feb 20, 2011 at 5:16 PM, Juergen Donnerstag
<ju...@gmail.com> 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 <jo...@gmail.com> 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 <ig...@gmail.com>wrote:
>>
>>> On Sat, Feb 19, 2011 at 2:20 PM, Juergen Donnerstag
>>> <ju...@gmail.com> 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 <ig...@gmail.com>
>>> 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 <jo...@gmail.com>
>>> 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 <joonas.hamalainen@gmail.com
>>> >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 <
>>> >>>> martin.makundi@koodaripalvelut.com> 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 <jo...@gmail.com>:
>>> >>>>> > 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 <
>>> >>>>> jeremy@wickettraining.com
>>> >>>>> >> wrote:
>>> >>>>> >
>>> >>>>> >> On Thu, Jan 20, 2011 at 1:51 PM, Igor Vaynberg <
>>> >>>>> igor.vaynberg@gmail.com
>>> >>>>> >> >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*
>>> >>>>> >>
>>> >>>>> >
>>> >>>>>
>>> >>>>
>>> >>>>
>>> >>>
>>> >>
>>> >
>>>
>>
>

Re: How to streamline ajax page region toggle

Posted by Joo Hama <jo...@gmail.com>.
Juergen, thanks for the review. I modified the code according to your
suggestions.

> - 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....

Good point, I fixed this by changing the simple variable to the sequence
value from Session class, making the id's session-unique. I also added an
unit test to verify this.

> - 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.

Right, I created a new InlineEnclosureHandler class and removed all the
changes
from EnclosureHandler. I also created a new InlineEnclosure class, extending
Enclosure.
Now the only modification in the Enclosure-class is that the visibility of
the method
getEnclosureParent() is relaxed to protected (was private), since the
extending
InlineEnclosure class uses the method as well.

I uploaded the new patch to JIRA.

https://issues.apache.org/jira/browse/WICKET-3422

- Joonas


On Sun, Feb 20, 2011 at 11:16 PM, Juergen Donnerstag <
juergen.donnerstag@gmail.com> 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 <jo...@gmail.com>
> 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 <igor.vaynberg@gmail.com
> >wrote:
> >
> >> On Sat, Feb 19, 2011 at 2:20 PM, Juergen Donnerstag
> >> <ju...@gmail.com> 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 <
> igor.vaynberg@gmail.com>
> >> 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 <
> joonas.hamalainen@gmail.com>
> >> 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 <
> joonas.hamalainen@gmail.com
> >> >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 <
> >> >>>> martin.makundi@koodaripalvelut.com> 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 <jo...@gmail.com>:
> >> >>>>> > 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 <
> >> >>>>> jeremy@wickettraining.com
> >> >>>>> >> wrote:
> >> >>>>> >
> >> >>>>> >> On Thu, Jan 20, 2011 at 1:51 PM, Igor Vaynberg <
> >> >>>>> igor.vaynberg@gmail.com
> >> >>>>> >> >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*
> >> >>>>> >>
> >> >>>>> >
> >> >>>>>
> >> >>>>
> >> >>>>
> >> >>>
> >> >>
> >> >
> >>
> >
>

Re: How to streamline ajax page region toggle

Posted by Juergen Donnerstag <ju...@gmail.com>.
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 <jo...@gmail.com> 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 <ig...@gmail.com>wrote:
>
>> On Sat, Feb 19, 2011 at 2:20 PM, Juergen Donnerstag
>> <ju...@gmail.com> 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 <ig...@gmail.com>
>> 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 <jo...@gmail.com>
>> 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 <joonas.hamalainen@gmail.com
>> >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 <
>> >>>> martin.makundi@koodaripalvelut.com> 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 <jo...@gmail.com>:
>> >>>>> > 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 <
>> >>>>> jeremy@wickettraining.com
>> >>>>> >> wrote:
>> >>>>> >
>> >>>>> >> On Thu, Jan 20, 2011 at 1:51 PM, Igor Vaynberg <
>> >>>>> igor.vaynberg@gmail.com
>> >>>>> >> >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*
>> >>>>> >>
>> >>>>> >
>> >>>>>
>> >>>>
>> >>>>
>> >>>
>> >>
>> >
>>
>

Re: How to streamline ajax page region toggle

Posted by Joo Hama <jo...@gmail.com>.
> 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 <ig...@gmail.com>wrote:

> On Sat, Feb 19, 2011 at 2:20 PM, Juergen Donnerstag
> <ju...@gmail.com> 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 <ig...@gmail.com>
> 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 <jo...@gmail.com>
> 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 <joonas.hamalainen@gmail.com
> >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 <
> >>>> martin.makundi@koodaripalvelut.com> 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 <jo...@gmail.com>:
> >>>>> > 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 <
> >>>>> jeremy@wickettraining.com
> >>>>> >> wrote:
> >>>>> >
> >>>>> >> On Thu, Jan 20, 2011 at 1:51 PM, Igor Vaynberg <
> >>>>> igor.vaynberg@gmail.com
> >>>>> >> >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*
> >>>>> >>
> >>>>> >
> >>>>>
> >>>>
> >>>>
> >>>
> >>
> >
>

Re: How to streamline ajax page region toggle

Posted by Igor Vaynberg <ig...@gmail.com>.
On Sat, Feb 19, 2011 at 2:20 PM, Juergen Donnerstag
<ju...@gmail.com> 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 <ig...@gmail.com> 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 <jo...@gmail.com> 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 <jo...@gmail.com>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 <
>>>> martin.makundi@koodaripalvelut.com> 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 <jo...@gmail.com>:
>>>>> > 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 <
>>>>> jeremy@wickettraining.com
>>>>> >> wrote:
>>>>> >
>>>>> >> On Thu, Jan 20, 2011 at 1:51 PM, Igor Vaynberg <
>>>>> igor.vaynberg@gmail.com
>>>>> >> >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*
>>>>> >>
>>>>> >
>>>>>
>>>>
>>>>
>>>
>>
>

Re: How to streamline ajax page region toggle

Posted by Juergen Donnerstag <ju...@gmail.com>.
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.

- Juergen


On Tue, Feb 8, 2011 at 7:34 AM, Igor Vaynberg <ig...@gmail.com> 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 <jo...@gmail.com> 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 <jo...@gmail.com>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 <
>>> martin.makundi@koodaripalvelut.com> 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 <jo...@gmail.com>:
>>>> > 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 <
>>>> jeremy@wickettraining.com
>>>> >> wrote:
>>>> >
>>>> >> On Thu, Jan 20, 2011 at 1:51 PM, Igor Vaynberg <
>>>> igor.vaynberg@gmail.com
>>>> >> >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*
>>>> >>
>>>> >
>>>>
>>>
>>>
>>
>

Re: How to streamline ajax page region toggle

Posted by Igor Vaynberg <ig...@gmail.com>.
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 <jo...@gmail.com> 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 <jo...@gmail.com>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 <
>> martin.makundi@koodaripalvelut.com> 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 <jo...@gmail.com>:
>>> > 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 <
>>> jeremy@wickettraining.com
>>> >> wrote:
>>> >
>>> >> On Thu, Jan 20, 2011 at 1:51 PM, Igor Vaynberg <
>>> igor.vaynberg@gmail.com
>>> >> >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*
>>> >>
>>> >
>>>
>>
>>
>