On Thu, Jul 11, 2013 at 5:22 PM, Martin Grigorov <[email protected]>wrote:
> > > > 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. > And they say this is a bad idea. jQuery.live() (deprecated in 1.7.0) did the same, bind on document, and it was slow. See http://api.jquery.com/live/ Also see http://www.ultimatewebtips.com/why-jquery-live-is-a-bad-option-to-use/ > > 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! >>>>> >>>>> >> >
