问题
We are using Wicket and our generated pages are quiet long (a lot of vertical scrolling). Some links or form's onSubmit
methods invoke just perform some actions on the database and show the same page again:
public class MyPage extends WebPage {
public MyPage(PageParameters parameters) {
....
final Form<Void> form = new StatelessForm<Void>("formId") {
protected void onSubmit() {
// some database stuff
...
setResponsePage(getClass(), getPageParameters());
}
};
...
}
}
How can I make the setResponsePage
invocation cause the browser scroll to the form, so the page is not just showing the top? Maybe some JavaScript-injection?
回答1:
I think a nice Wicket-y solution combines stuff that is already in Michael's answer, with a Behavior
, so you can just add
this to your form.
form.add( new ScrollToTopBehavior());
The behaviour itself would like something like this:
public class ScrollToTopBehavior extends Behavior
{
@Override
public void renderHead( Component component, IHeaderResponse response )
{
super.renderHead( component, response );
response.render( JavaScriptHeaderItem.forReference( Application.get().getJavaScriptLibrarySettings().getJQueryReference() ) );
component.setOutputMarkupId( true );
String script = String.format("doSomeJavaScriptStuff('%s')", component.getMarkupId());
response.render( OnDomReadyHeaderItem.forScript( script ) );
}
}
UPDATE:
For scrolling to a specific ID / ANCHOR only once, you can follow this answer: https://stackoverflow.com/a/3163635/461499
回答2:
JS of course.
This would be something like (with JQuery usage):
var scrollPosition = $('#scrollToMarkupId').offset().top;
$('html, body').animate({ scrollTop: " + scrollPosition + " }, 'slow');
where scrollToMarkupId
is wicket component's markup id, which could be obtained by calling component.getMarkupId()
method.
I'm not pro in JS, so you can try to google better impl may be.
Now, about wicket:
1) As for me, I prefer AJAX invocations for such behavior ( note that if you use such approach your page won't be stateless ):
// do not override your form's `onSubmit()` method
final Form<Void> form = new Form<Void>("formId");
// adding ajax behavior with `onSubmit()` method overriding.
form.add ( new AjaxFormSubmitBehavior ("submit")
{
protected void onSubmit ( AjaxRequestTarget target )
{
// your submit logic
// then insert js, descriped above:
target.appendJavaScript ("..." + componentToScroll.getMarkupId() + "..");
}
});
This approach won't reload your page at all but also post your data.
/----------------------------------------------------------------------------------------------------------------------------------/
2) You also could execute JS after page loading, by overriding renderHead
method:
public class YourPage extends WebPage
{
...
@Override
public void renderHead ( final IHeaderResponse response )
{
//replace `...` by your script.
response.render ( OnDomReadyHeaderItem.forScript ( "..." );
}
...
}
Such script will be invoked after page is renedered (and setResponsePage
method will render your page). You can use this approach for any components and panels too.
回答3:
I've now use following JavaScript injecting code:
add(new Behavior() {
@Override
public void renderHead(Component component, IHeaderResponse response) {
super.renderHead(component, response);
response.render(new HeaderItem() {
@Override
public Iterable<?> getRenderTokens() {
return Collections.singletonList("javascript-anchor");
}
@Override
public void render(Response response) {
response.write("<script type=\"text/javascript\">\n");
response.write("window.location.href='#rules';\n");
response.write("</script>\n");
}
});
}
});
Feel free to comment (I'm a complete JS-noob with only very limited experience in Wicket).
来源:https://stackoverflow.com/questions/27354911/wicket-tell-the-browser-to-scroll-to-certain-tag-anchor