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 7ffed09 commit 1cf9b6c
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@

import elemental2.dom.EventListener;
import elemental2.dom.HTMLElement;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.IntStream;
import org.dominokit.domino.ui.forms.suggest.Select;
import org.dominokit.domino.ui.forms.suggest.SelectOption;
Expand All @@ -47,6 +49,7 @@ public class AdvancedPagination extends BasePagination<AdvancedPagination> {

private Select<Integer> pagesSelect;
private PagerNavItem totalPagesCount;
private List<PagerNavItem> allPages = new LinkedList<>();

/**
* Creates a new instance of {@link AdvancedPagination} with default settings.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ public abstract class BasePagination<T extends BasePagination<T>>
protected NavElement pager;
protected UListElement pagesList;
protected PagerNavItem activePage;
protected List<PagerNavItem> allPages = new LinkedList<>();

private final Set<ChangeListener<? super Integer>> pageChangeListeners = new HashSet<>();
private boolean changeListenersPaused = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@
package org.dominokit.domino.ui.pagination;

import static java.util.Objects.nonNull;
import static org.dominokit.domino.ui.utils.Domino.*;
import static org.dominokit.domino.ui.style.SpacingCss.dui_text_ellipsis;
import static org.dominokit.domino.ui.utils.Domino.text;

import java.util.HashMap;
import java.util.Map;
import java.util.stream.IntStream;
import org.dominokit.domino.ui.icons.lib.Icons;
import org.dominokit.domino.ui.utils.BaseDominoElement;
Expand Down Expand Up @@ -50,6 +53,7 @@ public class ScrollingPagination extends BasePagination<ScrollingPagination> {
protected PagerNavItem prevSet;
protected PagerNavItem nextSet;
private final PagerNavItem totalCountNavItem;
private Map<Integer, PagerNavItem> activeWindow = new HashMap<>();

/**
* Creates a ScrollingPagination instance with default settings.
Expand Down Expand Up @@ -165,10 +169,10 @@ public ScrollingPagination(int pages, int pageSize, int windowSize) {
lastPage
.expand()
.getLink()
.addClickListener(evt -> moveToPage(allPages.size(), isChangeListenersPaused()))
.addClickListener(evt -> moveToPage(pagesCount, isChangeListenersPaused()))
.onKeyDown(
keyEvents ->
keyEvents.onEnter(evt -> moveToPage(allPages.size(), isChangeListenersPaused())));
keyEvents.onEnter(evt -> moveToPage(pagesCount, isChangeListenersPaused())));
nextSet
.expand()
.getLink()
Expand Down Expand Up @@ -235,25 +239,7 @@ public ScrollingPagination updatePages(int pages, int pageSize, boolean silent)
clearPages();

if (pages > 0) {
IntStream.rangeClosed(1, pages)
.forEach(
p -> {
PagerNavItem page =
PagerNavItem.page(p)
.addClickListener(evt -> moveToPage(p, isChangeListenersPaused()))
.onKeyDown(
keyEvents ->
keyEvents.onEnter(evt -> moveToPage(p, isChangeListenersPaused())));

if (p <= windowSize) {
if (allPages.isEmpty()) {
pagesList.insertAfter(page, prevPage);
} else {
pagesList.insertAfter(page, allPages.get(allPages.size() - 1));
}
}
allPages.add(page);
});
scrollToWindow(0);
}

dots.expand();
Expand Down Expand Up @@ -281,10 +267,37 @@ public ScrollingPagination updatePages(int pages, int pageSize, boolean silent)
return this;
}

private void scrollToWindow(int windowIndex) {
activeWindow.values().forEach(BaseDominoElement::remove);
activeWindow.clear();
final PagerNavItem[] lastPage = new PagerNavItem[1];
IntStream.rangeClosed(
(windowIndex * windowSize) + 1,
Math.min((windowIndex * windowSize) + windowSize, pagesCount))
.forEach(
p -> {
PagerNavItem page =
PagerNavItem.page(p)
.addClickListener(evt -> moveToPage(p, isChangeListenersPaused()))
.onKeyDown(
keyEvents ->
keyEvents.onEnter(evt -> moveToPage(p, isChangeListenersPaused())));

if (activeWindow.isEmpty()) {
pagesList.insertAfter(page, prevPage);
} else {
pagesList.insertAfter(page, lastPage[0]);
}
lastPage[0] = page;
activeWindow.put(p, page);
});
this.windowIndex = windowIndex;
}

/** Clears all pages from the pagination. */
private void clearPages() {
allPages.forEach(BaseDominoElement::remove);
allPages.clear();
activeWindow.values().forEach(BaseDominoElement::remove);
activeWindow.clear();
}

/**
Expand All @@ -298,9 +311,11 @@ protected void moveToPage(int page, boolean silent) {
PagerNavItem oldPage = activePage;
if (page > 0 && page <= pagesCount) {

showPageWindow(page);

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

if (!silent) {
Expand All @@ -326,8 +341,6 @@ protected void moveToPage(int page, boolean silent) {
prevSet.enable();
firstPage.enable();
}

showPageWindow(page);
}
}

Expand All @@ -337,47 +350,14 @@ protected void moveToPage(int page, boolean silent) {
* @param page The current page index.
*/
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 (page % windowSize == 0) {
scrollToWindow((page / windowSize) - 1);
} else {
nextSet.enable();
}
}

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()) {
pagesList.insertBefore(allPages.get(i), dots);
}
}

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

import static java.util.Objects.nonNull;

import java.util.LinkedList;
import java.util.List;
import java.util.stream.IntStream;
import org.dominokit.domino.ui.utils.BaseDominoElement;

Expand All @@ -39,6 +41,8 @@
*/
public class SimplePagination extends BasePagination<SimplePagination> {

private List<PagerNavItem> allPages = new LinkedList<>();

/**
* Creates a new instance of SimplePagination with default settings (0 pages and a page size of
* 10).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
font:var(--dui-pager-page-link-font);
text-align: center;
display: inline-block;
width: var(--dui-pager-page-link-size);
height: var(--dui-pager-page-link-size);
min-width: var(--dui-pager-page-link-size);
min-height: var(--dui-pager-page-link-size);
border-radius: var(--dui-pager-page-link-border-radius);
line-height: var(--dui-pager-page-link-size);
cursor: var(--dui-pager-page-link-cursor);
Expand Down

0 comments on commit 1cf9b6c

Please sign in to comment.