You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by "Hendy Irawan (JIRA)" <ji...@apache.org> on 2017/08/06 23:05:00 UTC

[jira] [Created] (WICKET-6439) Support auto-scroll for (Fenced)FeedbackPanel

Hendy Irawan created WICKET-6439:
------------------------------------

             Summary: 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
            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 they're using a traditional browser such as Opera Mini, 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 modern browser will see it. Unless they're using a traditional browser such as Opera Mini, which goes back to top and 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 and never come back.

Just for the sake of argument here's one goal flow that I'd like to increase its conversion rate :)

!wicketscroll.jpg|thumbnail!

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

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! :)



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