On Thu, Jul 11, 2013 at 4:48 PM, Sven Meier <[email protected]> wrote:
> Hi,
>
>
> >The idea with plain JS solution I cannot visualize in my head yet.
>
> EventDelegatingBehavior is just a collector of JavaScript snippets. The
> actual magic runs in the browser: a custom bubbling of events and
> delegation to the actual behavior.
> It should be possible to do this plain with JavaScript:
>
> public class DelegatingAjax implements IAjax {
>
> public ajax(IHeaderResponse response, Component component,
> AjaxRequestAttributes attributes) {
> CharSequence ajaxAttributes = renderAjaxAttributes(**component,
> attributes);
>
> response.render(**OnDomReadyHeaderItem.**forScript("Wicket.Event.***delegate*("
> + ajaxAttributes + ");");
> }
> }
>
> This would be page-global though.
This is an important detail!
I'll consult with my frontend colleagues but so far I don't see problems.
For every delegated component we can set special CSS class, e.g.
'wicket-delegated'.
The binding will be: $(document).on('click', '.wicket-delegated',
function(event) {....})
i.e. we will take advantage of jQuery delegation/live support.
This way even newly added items in the repeaters will be automatically
supported.
>
>
> Sven
>
>
>
> On 07/11/2013 03:40 PM, Martin Grigorov wrote:
>
>> On Thu, Jul 11, 2013 at 4:30 PM, Nick Pratt <[email protected]> wrote:
>>
>> I think this is great - we have some tables now with a ton of JS events
>>> on
>>> the child elements. Just to clarify, will this make the rendered page
>>> smaller since there will only be a single JS handler for the event for
>>> the
>>> container rather than N JS handlers?
>>>
>>> At the moment all attributes for an inner element are preserved.
>> 'e' (the event name), 'c' (the component markup id), pd (prevent default),
>> sp (stop propagation) can be removed because they are not really used.
>> But every inner element can have its own call listeners, form submitters
>> can also have custom settings ('f', 'sc', 'mp', 'm'), so I think they have
>> to be preserved.
>> If you look in #updateAjaxAttributes() for your ajax behaviors in your
>> table cells you will probably notice that they have their own attributes.
>>
>>
>> Making it switchable (I think how Sven suggested) would be an
>>> improvement -
>>> we could leave it off by default, but provide a simple switch on a
>>> per-container (or per-app) basis that would allow the dev to choose.
>>>
>>> Yes, it looks as an improvement.
>> Moving the current code to such implementation is easy.
>> The idea with plain JS solution I cannot visualize in my head yet.
>>
>>
>> Regards
>>>
>>> Nick
>>>
>>> On Thu, Jul 11, 2013 at 4:59 AM, Martin Grigorov <[email protected]
>>>
>>>> wrote:
>>>> Hi,
>>>>
>>>> At https://github.com/apache/**wicket/compare/event-**
>>>> delegating-behavioryou<https://github.com/apache/wicket/compare/event-delegating-behavioryou>
>>>> may see the diff between master and event-delegating-behavior branches.
>>>>
>>>> The latter provides a new AjaxEventBehavior (AEB) -
>>>>
>>> EventDelegatingBehavior
>>>
>>>> (EDB), that suppresses the JS event binding for all AjaxEventBehaviors
>>>>
>>> for
>>>
>>>> a given event type (click, submit, change, ...) in the children
>>>>
>>> components
>>>
>>>> of the host component of EDB.
>>>>
>>>> How EDB works:
>>>>
>>>> - until now AjaxEventBehavior#renderHead() renders ondomready header
>>>> item
>>>> with JS snippet like:
>>>> Wicket.Ajax.ajax(**attributesObject);
>>>> In the new branch there is a check if some parent has EDB for the event
>>>> type of this AEB, and if there is such then the AEB "donates" its
>>>> attributes to the EDB.
>>>>
>>>> - EventDelegatingBehavior#**getCallbackScript() renders :
>>>> Wicket.Event.delegate('**edbComponentMarkupId', 'eventType',
>>>> edbAttributes,
>>>> childrenAttrsMap);
>>>>
>>>> - when a delegated component fires its event (e.g. the user clicks on an
>>>> AjaxLink) the event is handled by EDB's event handler. It extracts the
>>>> markupId of the inner HTML element and fires Wicket.Ajax.Call with the
>>>> specific attributes for the extracted inner element.
>>>>
>>>> Pros:
>>>>
>>>> - simple to use - just add EDB to a container component around your Ajax
>>>> heavy component (e.g. repeater with many Ajax behaviors). See the demo
>>>>
>>> app
>>>
>>>> at
>>>> https://issues.apache.org/**jira/browse/WICKET-5267<https://issues.apache.org/jira/browse/WICKET-5267>
>>>>
>>>> - faster JS execution
>>>> -- faster execution of the domready handler because there is just one
>>>> binding instead of N
>>>> -- faster reaction because the browser finds the event handler much
>>>>
>>> faster.
>>>
>>>> I wasn't able to prove this with numbers because there is no way to
>>>>
>>> detect
>>>
>>>> the 'start time', i.e. when the user makes the action. With JS the
>>>>
>>> earliest
>>>
>>>> point is when the browser has already looked up the event handler.
>>>> Chrome Dev tools (timeline, profiling, pagespeed) don't help too. So my
>>>> reference that it is faster are the articles in the web and a use case
>>>> in
>>>> our application.
>>>>
>>>> Cons:
>>>>
>>>> - AEB#renderHead() needs to check whether there is EDB up in the
>>>>
>>> hierarchy
>>>
>>>> to be able to decide what to do.
>>>> This is ugly, I agree. But I see no other solution that will preserve
>>>> the
>>>> transparent usage of something like EDB and will not require a major
>>>> rewrite of user applications to be able to use event delegation.
>>>> -- there are some optimizations to lower the impact of the new checks:
>>>> --- a new setting (IAjaxSettings#**useEventDelegation) - a global
>>>> property
>>>> that prevents visiting the parent components and their behaviors for all
>>>> apps which do not use EDB
>>>> --- when EDB is bound it registers a metadata for its event type in the
>>>> page instance. This prevents visiting all behaviors of all parent
>>>> components
>>>>
>>>>
>>>> I have no more ideas how to further optimize it.
>>>>
>>>> Any feedback is welcome! Even if you have a completely different idea
>>>> how
>>>> to implement this functionality.
>>>>
>>>> Thanks for reading!
>>>>
>>>>
>