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

Hendy Irawan updated WICKET-6439:
---------------------------------
    Description: 
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 (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!
!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. 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! :)

  was:
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 (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!
!wicketscroll.jpg|thumbnail! (attachment image not shown for some reason: 
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. 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! :)


> 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 (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!
> !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. 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)

Reply via email to