Java tutorial
/** * Copyright (C) 2014 Premium Minds. * * This file is part of pm-wicket-utils. * * pm-wicket-utils is free software: you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * pm-wicket-utils is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with pm-wicket-utils. If not, see <http://www.gnu.org/licenses/>. */ package com.premiumminds.webapp.wicket; import java.util.List; import org.apache.wicket.AttributeModifier; import org.apache.wicket.Component; import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.behavior.Behavior; import org.apache.wicket.markup.head.IHeaderResponse; import org.apache.wicket.markup.head.JavaScriptHeaderItem; import org.apache.wicket.markup.head.OnDomReadyHeaderItem; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.list.ListItem; import org.apache.wicket.markup.html.list.ListView; import org.apache.wicket.model.LoadableDetachableModel; import org.apache.wicket.model.Model; import org.apache.wicket.request.resource.JavaScriptResourceReference; import org.apache.wicket.request.resource.ResourceReference; public abstract class InfiniteScrollListView<T> extends WebMarkupContainer { private static final long serialVersionUID = 3906374470444741117L; private static final int MAX_ELEMENTS = 100; private static final int SCROLL_SIZE = 20; private static final ResourceReference javascriptReference = new JavaScriptResourceReference( InfiniteScrollListView.class, "InfiniteScrollListView.js"); private WebMarkupContainer listContainer; private WebMarkupContainer upLoading; private WebMarkupContainer downLoading; private ListView<T> listView; private AbstractDefaultAjaxBehavior upBehavior; private AbstractDefaultAjaxBehavior downBehavior; public InfiniteScrollListView(String id, PageableListModel<? extends List<? extends T>> model) { super(id, model); } @SuppressWarnings("serial") @Override protected void onInitialize() { super.onInitialize(); setOutputMarkupPlaceholderTag(true); add(listContainer = new WebMarkupContainer("list")); listContainer.setOutputMarkupPlaceholderTag(true); listContainer.add(upLoading = new WebMarkupContainer("upLoading")); upLoading.setOutputMarkupPlaceholderTag(true); upLoading.setVisible(false); add(upBehavior = new AbstractDefaultAjaxBehavior() { private static final long serialVersionUID = -1895111598850513557L; @Override protected void respond(AjaxRequestTarget target) { target.appendJavaScript("InfiniteScroll.getFromContainer('" + InfiniteScrollListView.this.getMarkupId() + "').scrollDownTo('" + getItemMarkupId(InfiniteScrollListView.this.getModel().getObject().get(0)) + "')"); setStartIndex(InfiniteScrollListView.this.getModel().getStartIndex() - SCROLL_SIZE); refreshLoadings(); target.add(listContainer); } }); listView = new ListView<T>("list", new LoadableDetachableModel<List<? extends T>>() { @Override protected List<? extends T> load() { return getModel().getObject(); } }) { private static final long serialVersionUID = -1218380580005295126L; @Override protected void populateItem(ListItem<T> item) { InfiniteScrollListView.this.populateItem(item); item.setMarkupId(getItemMarkupId(item.getModelObject())); } @Override public void renderHead(IHeaderResponse response) { String containerId = InfiniteScrollListView.this.getMarkupId(); response.render( JavaScriptHeaderItem.forReference(javascriptReference, "infinite-scroll-list-view-js")); response.render(OnDomReadyHeaderItem.forScript("InfiniteScroll.getFromContainer('" + containerId + "').changeUp(" + Boolean.toString(isShowUpLoading()) + ")")); response.render(OnDomReadyHeaderItem.forScript("InfiniteScroll.getFromContainer('" + containerId + "').changeDown(" + Boolean.toString(isShowDownLoading()) + ")")); super.renderHead(response); } }; listContainer.add(listView); listContainer.add(downLoading = new WebMarkupContainer("downLoading")); downLoading.setOutputMarkupPlaceholderTag(true); downLoading.setVisible(getModel().getSize() > MAX_ELEMENTS); add(downBehavior = new AbstractDefaultAjaxBehavior() { private static final long serialVersionUID = -1895111598850513557L; @Override protected void respond(AjaxRequestTarget target) { target.appendJavaScript( "InfiniteScroll.getFromContainer('" + InfiniteScrollListView.this.getMarkupId() + "')" + ".scrollUpTo('" + getItemMarkupId(InfiniteScrollListView.this.getModel().getObject() .get(Math.min(InfiniteScrollListView.this.getModel().getViewSize() - 1, InfiniteScrollListView.this.getModel().getObject().size() - 1))) + "')"); setStartIndex(getModel().getStartIndex() + SCROLL_SIZE); refreshLoadings(); target.add(listContainer); } }); add(getScrollBehaviour()); } protected abstract void populateItem(final ListItem<T> item); protected abstract String getItemMarkupId(final T item); private Behavior getScrollBehaviour() { return new AttributeModifier("onscroll", Model.of(this.getMarkupId())) { private static final long serialVersionUID = 3523727356782417598L; @Override public void renderHead(Component component, IHeaderResponse response) { super.renderHead(component, response); response.render(OnDomReadyHeaderItem .forScript("InfiniteScroll.getFromContainer('" + getMarkupId() + "').setUrls('" + upBehavior.getCallbackUrl() + "', '" + downBehavior.getCallbackUrl() + "')")); } @Override protected String newValue(String currentValue, String replacementValue) { return "InfiniteScroll.handleScroll('" + InfiniteScrollListView.this.getMarkupId() + "')"; } }; } @Override protected void onBeforeRender() { setStartIndex(0); refreshLoadings(); super.onBeforeRender(); } private boolean isShowUpLoading() { return getModel().getStartIndex() > 0; } private boolean isShowDownLoading() { return getModel().getSize() - getModel().getStartIndex() > MAX_ELEMENTS; } private void setStartIndex(int index) { getModel().setStartIndex(index, MAX_ELEMENTS); } @SuppressWarnings("unchecked") public PageableListModel<? extends List<? extends T>> getModel() { return (PageableListModel<? extends List<? extends T>>) getDefaultModel(); } public void setModel(PageableListModel<? extends List<? extends T>> model) { setDefaultModel(model); } private void refreshLoadings() { upLoading.setVisible(isShowUpLoading()); downLoading.setVisible(isShowDownLoading()); } }