[ 
https://issues.apache.org/jira/browse/WICKET-6439?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Sven Meier closed WICKET-6439.
------------------------------
    Resolution: Invalid
      Assignee: Sven Meier

You can use your own subclass of FencedFeedbackPanel, which has its 
renderHead() rendering some JavaScript to scroll itself into view.

Please ask on the user mailing list if you need further help in implementing 
this.

> Support auto-scroll for (Fenced)FeedbackPanel
> ---------------------------------------------
>
>                 Key: WICKET-6439
>                 URL: https://issues.apache.org/jira/browse/WICKET-6439
>             Project: Wicket
>          Issue Type: Improvement
>          Components: wicket
>    Affects Versions: 7.8.0
>            Reporter: Hendy Irawan
>            Assignee: Sven Meier
>            Priority: Minor
>         Attachments: wicketscroll.jpg
>
>
> My use case is exactly the same as described in 
> https://stackoverflow.com/questions/27172854/how-to-automatically-scroll-up-a-wicket-panel-when-wicket-feedbackpanel-is-trigg
> Allow me to elaborate.
> Assuming a mobile browser or any viewport size that can't display the full 
> page: When user clicks the (ajax) Submit button and there's error, without 
> this functionality, there are two scenarios:
> 1. If the FeedbackPanel is on top, the user won't see it. Unless it's a 
> stateless form, which then goes back to top. Either way they *still* have to 
> scroll up or down to find the field.
> 2. If the FeedbackPanel is right above the button, only users with working 
> Ajax will see it and only for ajax forms. Else it back to top and they won't 
> see it. Either way they *still* have to scroll up or down to find the field.
> Some users find this disorienting and I suspect this is the cause some people 
> leave and never come back.
> Just for the sake of argument here's one goal flow (almost half of the users 
> go away on the very first form) that I'd like to increase its conversion rate 
> :)
> !https://issues.apache.org/jira/secure/attachment/12880581/wicketscroll.jpg!
> Proposed solution is simple, scroll to the FeedbackPanel message, which is 
> optimally placed right on top of the first offending field (in case there are 
> several). But some problems I encountered while trying to get solve this:
> 1. With {{Form.onError()}} it's trivial to do this when there's only one 
> FeedbackPanel. But with multiple {{FencedFeedbackPanel}}s there needs to be 
> some logic to (1) know which of the FeedbackPanels gets which message, and 
> (2) determine the "top-most" (based on component hierarchy), before (3) 
> appending JavaScript to scroll there.
> 2. Even with point 1 solved, I still need to duplicate that logic on every 
> form on every page. It'd be great if this logic can be put directly in the 
> FeedbackPanel itself. I've tried it using hint from 
> https://stackoverflow.com/questions/19246892/how-to-get-the-ajaxrequesttarget-inside-wickets-onbeforerender-method-of-a-co
>  but I can't even get any messages, any method I try simply gave either null 
> or Array[] :
> {code:java}
> public class ScrollNotificationPanel extends NotificationPanel {
>     @Override
>     protected void onInitialize() {
>         super.onInitialize();
>         setOutputMarkupId(true);
>     }
>     @Override
>     protected void onAfterRender() {
>         super.onAfterRender();
>         final AjaxRequestTarget target = 
> getRequestCycle().find(AjaxRequestTarget.class);
>         if (null != target) {
>             final Object modelObject = newFeedbackMessagesModel().getObject();
> //            final List<FeedbackMessage> feedbackMessages = 
> getFeedbackMessagesModel().getObject();
>             final String msgs = JsonUtils.asJson(modelObject);
>             target.appendJavaScript("console.log('horaXXXXXy', " + msgs + 
> ");");
>         }
>         if (null != target && 
> getFeedbackMessages().hasMessage(FeedbackMessage.ERROR)) {
>             String scrollScript = "$('html, body').animate({scrollTop:$('#" + 
> getMarkupId() + "').offset().top - 20}, 'slow');\n";
>             target.appendJavaScript(scrollScript);
>         }
>     }
>     @Override
>     protected void onBeforeRender() {
>         super.onBeforeRender();
>         final AjaxRequestTarget target = 
> getRequestCycle().find(AjaxRequestTarget.class);
>         if (null != target) {
>             final Object modelObject = newFeedbackMessagesModel().getObject();
> //            final List<FeedbackMessage> feedbackMessages = 
> getFeedbackMessagesModel().getObject();
>             final String msgs = JsonUtils.asJson(modelObject);
>             target.appendJavaScript("console.log('horay', " + msgs + ");");
>         }
>         if (null != target && 
> getFeedbackMessages().hasMessage(FeedbackMessage.ERROR)) {
>             String scrollScript = "$('html, body').animate({scrollTop:$('#" + 
> getMarkupId() + "').offset().top - 20}, 'slow');\n";
>             target.appendJavaScript(scrollScript);
>         }
>     }
> }
> {code}
> 3. There needs to be some "buffer" on top when scrolling. For example, most 
> websites have a floating navbar on top, and scrolling right to a panel will 
> make the panel covered by the navbar. So there should be a buffer value, 20 
> is a sane minimal value for comfort, but some websites (like mine) will need 
> to adjust it to 50 or something else.
> 4. Added bonus if this can work with non-JavaScript (i.e. 
> Button/AjaxFallbackButton) / stateless forms. Technically it's possible by 
> using the URL fragment, i.e. FeedbackPanel's outputMarkupId will need to be 
> true, and the "next" page need to redirect to a fragment. However I have no 
> idea how to do this robustly.
> (5. I know an edge case: horizontal scrolling, yet I personally don't care 
> because IMHO if there's a horizontal scroll visible the page needs to fix its 
> UX first.)
> So I hope you accept this proposal or at least give me hints on how to do 
> point 1 & 2 above. If this gets implemented in Wicket this should be a flag 
> instead of a new component, and I hope it's enabled by default (if not in 
> Wicket 7 then hopefully for Wicket 8).
> Thank you in advance Martin! :)
> ---
> I just did a browser test and:
> 1. The only method that partially works on Opera Mini is {{location.hash}}. 
> Problem: 1. it only works on first submit; 2. if there's a floating navbar it 
> will get covered on modern browsers, but not in Opera Mini that doesn't 
> support floating navbar. Neither .scrollTop nor jQuery.scrollTo works 
> (https://github.com/flesler/jquery.scrollTo/issues/158)
> 2. On modern browsers {{$('html, body').animate({scrollTop}} works reliably. 
> https://github.com/flesler/jquery.scrollTo might be used for extra features 
> that some people want, but I don't think you'd like that bundled with Wicket, 
> so basic jQuery method works very well.
> For me, I'd probably browser sniff Opera Mini and serve location.hash, else 
> animate-scrollTop.



--
This message was sent by Atlassian JIRA
(v6.4.14#64029)

Reply via email to