Skip to content

Commit

Permalink
fix #994 ScrollingPagination performance for large number of pages
Browse files Browse the repository at this point in the history
  • Loading branch information
vegegoku committed Jan 5, 2025
1 parent e18077f commit 00e7eaf
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import static org.jboss.elemento.Elements.li;

import elemental2.dom.*;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.IntStream;
import org.dominokit.domino.ui.forms.Select;
Expand All @@ -41,6 +43,7 @@ public class AdvancedPagination extends BasePagination<AdvancedPagination> {

private Function<Integer, String> pagesCountTextHandler =
pagesCount -> " of " + pagesCount + " Pages";
private List<DominoElement<? extends HTMLElement>> allPages = new LinkedList<>();

/** @return new instance */
public static AdvancedPagination create() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@

import elemental2.dom.HTMLElement;
import elemental2.dom.HTMLUListElement;
import java.util.LinkedList;
import java.util.List;
import org.dominokit.domino.ui.utils.BaseDominoElement;
import org.dominokit.domino.ui.utils.DominoElement;

Expand All @@ -38,7 +36,6 @@ public abstract class BasePagination<T extends BasePagination<T>>
protected DominoElement<? extends HTMLElement> prevElement;
protected DominoElement<? extends HTMLElement> nextElement;

protected List<DominoElement<? extends HTMLElement>> allPages = new LinkedList<>();
protected PageChangedCallBack pageChangedCallBack = pageIndex -> {};
protected String size = "pagination-default";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,18 @@
*/
package org.dominokit.domino.ui.pagination;

import static java.util.Objects.nonNull;
import static org.jboss.elemento.Elements.a;
import static org.jboss.elemento.Elements.li;

import elemental2.dom.HTMLAnchorElement;
import elemental2.dom.HTMLElement;
import elemental2.dom.HTMLLIElement;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.IntStream;
import org.dominokit.domino.ui.icons.Icons;
import org.dominokit.domino.ui.style.Styles;
import org.dominokit.domino.ui.utils.BaseDominoElement;
import org.dominokit.domino.ui.utils.DominoElement;

/** A scrolling pagination implementation */
Expand All @@ -46,6 +50,7 @@ public class ScrollingPagination extends BasePagination<ScrollingPagination> {
private final int windowSize;
private int windowIndex = 0;
private boolean totalRecordVisible = false;
private Map<Integer, DominoElement<? extends HTMLElement>> activeWindow = new HashMap<>();

/** @return new instance */
public static ScrollingPagination create() {
Expand Down Expand Up @@ -111,7 +116,6 @@ public ScrollingPagination updatePages(int pages, int pageSize, boolean silent)
this.pageSize = pageSize;
this.pagesCount = pages;
this.index = 1;
allPages.clear();

prevAnchor = DominoElement.of(a());
prevElement =
Expand Down Expand Up @@ -147,22 +151,7 @@ public ScrollingPagination updatePages(int pages, int pageSize, boolean silent)
.appendChild(prevElement);

if (pages > 0) {
IntStream.rangeClosed(1, pages)
.forEach(
p ->
DominoElement.of(li())
.css("page")
.apply(
element -> {
element.appendChild(
DominoElement.of(a())
.setTextContent(p + "")
.addClickListener(evt -> moveToPage(p, false)));
allPages.add(element);
if (p <= windowSize) {
pagesElement.appendChild(element);
}
}));
scrollToWindow(0);
}

if (pages > windowSize) {
Expand Down Expand Up @@ -218,7 +207,7 @@ public ScrollingPagination updatePages(int pages, int pageSize, boolean silent)
.appendChild(
lastPageAnchor
.appendChild(Icons.ALL.skip_next().clickable())
.addClickListener(event -> moveToPage(allPages.size(), false)));
.addClickListener(event -> moveToPage(pagesCount, false)));

if (pages > 0) {
moveToPage(1, silent);
Expand All @@ -241,14 +230,53 @@ public ScrollingPagination updatePages(int pages, int pageSize, boolean silent)
return this;
}

private void scrollToWindow(int windowIndex) {
activeWindow.values().forEach(BaseDominoElement::remove);
activeWindow.clear();
final DominoElement<? extends HTMLElement>[] lastPage = new DominoElement[1];
IntStream.rangeClosed(
(windowIndex * windowSize) + 1,
Math.min((windowIndex * windowSize) + windowSize, pagesCount))
.forEach(
p -> {
DominoElement.of(li())
.css("page")
.apply(
element -> {
element.appendChild(
DominoElement.of(a())
.setTextContent(p + "")
.apply(
self -> {
if (p > 9999) {
self.addCss(Styles.ellipsis_text)
.setTooltip(String.valueOf(p));
}
})
.addClickListener(evt -> moveToPage(p, false)));

if (activeWindow.isEmpty()) {
pagesElement.insertAfter(element, prevElement);
} else {
pagesElement.insertAfter(element, lastPage[0]);
}
lastPage[0] = element;
activeWindow.put(p, element);
});
});
this.windowIndex = windowIndex;
}

/** {@inheritDoc} */
@Override
protected void moveToPage(int page, boolean silent) {
if (page > 0 && page <= pagesCount) {

showPageWindow(page);

index = page;
if (markActivePage) {
gotoPage(allPages.get(page - 1));
gotoPage(activeWindow.get(page));
}

if (!silent) {
Expand All @@ -274,69 +302,18 @@ protected void moveToPage(int page, boolean silent) {
prevSet.enable();
firstPage.enable();
}

showPageWindow(page);
}
}

private void showPageWindow(int page) {
if (page % windowSize == 0) {
showWindow((page / windowSize) - 1);
} else {
showWindow(page / windowSize);
}

if (windowIndex == 0) {
prevSet.disable();
} else {
prevSet.enable();
if (activeWindow.containsKey(page)) {
return;
}

int windowCount = (allPages.size() / windowSize) + (allPages.size() % windowSize > 0 ? 1 : 0);
if (windowIndex >= windowCount - 1) {
nextSet.disable();
if (nonNull(dotsElement) && nonNull(pagesCountPageElement)) {
dotsElement.hide();
pagesCountPageElement.hide();
}

if (page % windowSize == 0) {
scrollToWindow((page / windowSize) - 1);
} else {
nextSet.enable();
if (nonNull(dotsElement) && nonNull(pagesCountPageElement)) {
dotsElement.show();
pagesCountPageElement.show();
}
}
}

private void showWindow(int index) {

if (index != this.windowIndex) {
int windowMinLimit = windowIndex * windowSize;
int windowMaxLimit = windowMinLimit + windowSize;

for (int i = windowMinLimit; i < windowMaxLimit; i++) {
if (i < allPages.size()) {
allPages.get(i).remove();
}
}

int targetWindowMinLimit = index * windowSize;
int targetWindowMaxLimit = targetWindowMinLimit + windowSize;

for (int i = targetWindowMinLimit; i < targetWindowMaxLimit; i++) {
if (i < allPages.size()) {
if (pagesElement.contains(dotsElement)) {
pagesElement.insertBefore(allPages.get(i), dotsElement);
} else if (pagesElement.contains(pagesCountPageElement)) {
pagesElement.insertBefore(allPages.get(i), pagesCountPageElement);
} else {
pagesElement.appendChild(allPages.get(i));
}
}
}

this.windowIndex = index;
scrollToWindow(page / windowSize);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
import static org.jboss.elemento.Elements.li;

import elemental2.dom.HTMLAnchorElement;
import elemental2.dom.HTMLElement;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.IntStream;
import org.dominokit.domino.ui.icons.Icons;
import org.dominokit.domino.ui.utils.DominoElement;
Expand All @@ -28,6 +31,7 @@ public class SimplePagination extends BasePagination<SimplePagination> {

private DominoElement<HTMLAnchorElement> prevAnchor;
private DominoElement<HTMLAnchorElement> nextAnchor;
private List<DominoElement<? extends HTMLElement>> allPages = new LinkedList<>();

/** @return new instance */
public static SimplePagination create() {
Expand Down

0 comments on commit 00e7eaf

Please sign in to comment.