Skip to content

Commit

Permalink
MWPW-164728 [MMM] Improve design of pagination (#3669)
Browse files Browse the repository at this point in the history
* after history reset

* opcity change remove dropdown disabled

* comment cleanup

* createPageList fix added search params

* search param update

* remove perpage pagenum from shareurl hrefs

* comment changes

---------

Co-authored-by: Denys Fedotov <[email protected]>
  • Loading branch information
ivanvatadobe and Denys Fedotov authored Feb 20, 2025
1 parent 05409ce commit fd41709
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 46 deletions.
50 changes: 47 additions & 3 deletions libs/blocks/mmm/mmm.css
Original file line number Diff line number Diff line change
Expand Up @@ -491,14 +491,13 @@ dd .mep-popup-header .mep-close {
pointer-events: none;
}
#mmm-pagination .arrow {
font-size: 1.5rem;
font-weight: 600;
}

.mmm-pagination-summary {
display: flex;
justify-content: flex-end;
padding: 0 0 .5rem;
padding: 0 0;
}

main > .section > .share-mmm.inline {
Expand Down Expand Up @@ -528,4 +527,49 @@ main > .section > .inline-wrapper > .share-mmm.inline {
#mmm-pagination {
padding: 2rem 4rem;
}
}
}

/* pagination */
#mmm-pagination-wrapper {
width: 100%;
display: flex;
gap: 10px;
justify-content: right;
flex-direction: row;
}

#pagination-select {
align-items: center;
}

#mmm-pagination-wrapper label,
#mmm-pagination-wrapper span {
font-size: 12px;
font-weight: 400;
text-align: left;
}

#mmm-pagination-dropdown {
min-width: 90px;
height: 36px;
border-radius: 4px;
margin-right: 20px;
}

#pagination-arrows,
#pagination-select {
display: flex;
gap: 10px;
align-items: center;
}

#pagination-arrows a:not(.disabled) {
color: #000;
cursor: pointer;
}

#pagination-arrows a.disabled svg {
opacity: .4;
}


140 changes: 97 additions & 43 deletions libs/blocks/mmm/mmm.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ const SEARCH_INITIAL_VALUES = getInitialValues() ?? {
lastSeenManifest: LAST_SEEN_OPTIONS.threeMonths.key,
pageNum: 1,
subdomain: SUBDOMAIN_OPTIONS.www.key,
perPage: 25,
};

async function toggleDrawer(target, dd, pageId) {
Expand Down Expand Up @@ -123,7 +124,7 @@ function createButtonDetailsPair(mmmEl, page) {
* @param {Number} pageNum - optional. Number of the clicked page.
* @param {Event} event - optional. Page number click Event object.
*/
function filterPageList(pageNum, event) {
function filterPageList(pageNum, perPage, event) {
const shareUrl = new URL(`${window.location.origin}${window.location.pathname}`);
const searchValues = {};
const activeSearchWithShortKeyword = event?.target?.value && event.target.value.length < 2;
Expand All @@ -138,9 +139,9 @@ function filterPageList(pageNum, event) {
if (value) shareUrl.searchParams.set(id, value);
});

// add page number to share url
shareUrl.searchParams.set('pageNum', pageNum || 1);
// add pageNum and perPage to args for api call
searchValues.pageNum = { value: pageNum || 1, tagName: 'A' };
searchValues.perPage = { value: perPage || 25, tagName: 'SELECT' };

// assemble event details object with all filter criterias
const detail = {};
Expand Down Expand Up @@ -269,8 +270,8 @@ function createSearchField() {
const searchField = searchForm.querySelector('textarea');
searchField.value = SEARCH_INITIAL_VALUES.filter || '';

searchField.addEventListener('keyup', debounce((event) => filterPageList(null, event)));
searchField.addEventListener('change', debounce((event) => filterPageList(null, event)));
searchField.addEventListener('keyup', debounce((event) => filterPageList(null, null, event)));
searchField.addEventListener('change', debounce((event) => filterPageList(null, null, event)));
searchField.addEventListener('input', function adjustHeight() {
this.style.height = 'auto'; /* Reset height to auto to recalculate */
this.style.height = `${this.scrollHeight - 32}px`;
Expand Down Expand Up @@ -314,51 +315,103 @@ async function createForm(el) {
}

function createPaginationEl({ data, el }) {
const paginationEl = createTag('div', { id: 'mmm-pagination', 'data-current-page': data.pageNum });
const totalPages = Math.ceil(data.totalRecords / data.perPage);
const noResult = !data.totalRecords;
const prev = data.pageNum - 1 || 1;
const next = data.pageNum < totalPages ? data.pageNum + 1 : data.pageNum;

const prevEl = createTag('a', {
'data-page-num': prev,
class: `arrow ${data.pageNum === 1 ? 'disabled' : ''}`,
}, '<');
const nextEl = createTag('a', {
'data-page-num': next,
class: `arrow ${data.pageNum === totalPages ? 'disabled' : ''}`,
}, '>');

const paginationSummary = createTag('div', { class: 'mmm-pagination-summary' });
const range = `${data.pageNum * data.perPage - (data.perPage - 1)}-${data.pageNum * data.perPage < data.totalRecords ? data.pageNum * data.perPage : data.totalRecords}`;
paginationSummary.innerHTML = `
<div>
<span>${range} of ${data.totalRecords}</span>
<div>
`;
if (!noResult) {
paginationEl.append(prevEl);
for (let i = 1; i <= totalPages; i += 1) {
const pageLink = createTag('a', {
class: `${i === data.pageNum ? 'current-page' : ''}`,
'data-page-num': i,
}, i);
paginationEl.append(pageLink);
}
paginationEl.append(nextEl);
document.querySelector('#mmm').prepend(paginationSummary);
const { pageNum, perPage, totalRecords } = data;
const arrowIcons = {
first: '<svg width="14" height="12" viewBox="0 0 14 12" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M13.205 10.59L8.61504 6L13.205 1.41L11.795 0L5.79504 6L11.795 12L13.205 10.59ZM0.795044 0H2.79504V12H0.795044V0Z" fill="black"/></svg>',
prev: '<svg width="8" height="12" viewBox="0 0 8 12" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M7.70504 1.41L6.29504 0L0.295044 6L6.29504 12L7.70504 10.59L3.12504 6L7.70504 1.41Z" fill="black"/></svg>',
next: '<svg width="8" height="12" viewBox="0 0 8 12" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1.70504 0L0.295044 1.41L4.87504 6L0.295044 10.59L1.70504 12L7.70504 6L1.70504 0Z" fill="black"/></svg>',
last: '<svg width="14" height="12" viewBox="0 0 14 12" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M0.795044 1.41L5.38504 6L0.795044 10.59L2.20504 12L8.20504 6L2.20504 0L0.795044 1.41ZM11.205 0H13.205V12H11.205V0Z" fill="black"/></svg>',
};
const paginationEl = createTag('div', {
id: 'mmm-pagination',
'data-current-page': pageNum,
'data-perpage': perPage,
});
if (totalRecords) {
const perPageOptions = [25, 50, 100]; // add more options as needed
const paginationWrapper = createTag('div', { id: 'mmm-pagination-wrapper' });
const paginationLabel = createTag(
'label',
{ for: 'mmm-pagination-dropdown' },
'Items per page:',
);
const paginationDropdown = createTag(
'select',
{
id: 'mmm-pagination-dropdown',
value: perPage,
},
);
perPageOptions.forEach((option) => paginationDropdown.append(createTag('option', {
value: option,
...(option === perPage ? { selected: 'selected' } : {}),
}, option)));
paginationEl.append(paginationWrapper);
const totalPages = Math.ceil(totalRecords / perPage);
const prev = pageNum - 1 || 1;
const next = pageNum < totalPages ? pageNum + 1 : pageNum;
const firstEl = createTag('a', {
'data-page-num': '1',
class: `arrow ${pageNum === 1 ? 'disabled' : ''}`,
}, arrowIcons.first);
const prevEl = createTag('a', {
'data-page-num': prev,
class: `arrow ${pageNum === 1 ? 'disabled' : ''}`,
}, arrowIcons.prev);
const nextEl = createTag('a', {
'data-page-num': next,
class: `arrow ${pageNum === totalPages ? 'disabled' : ''}`,
}, arrowIcons.next);
const lastEl = createTag('a', {
'data-page-num': totalPages,
class: `arrow ${pageNum === totalPages ? 'disabled' : ''}`,
}, arrowIcons.last);
const rangeStart = pageNum * perPage - (perPage - 1);
const rangeEnd = pageNum * perPage < totalRecords ? pageNum * perPage : totalRecords;
const range = `${rangeStart.toLocaleString()} - ${rangeEnd.toLocaleString()}`;
const paginationSummary = createTag(
'div',
{ class: 'mmm-pagination-summary' },
`<div><span>${range} of ${totalRecords.toLocaleString()}</span><div>`,
);
paginationWrapper.append(
createTag('div', { id: 'pagination-select' }, [paginationLabel, paginationDropdown]),
createTag('div', { id: 'pagination-arrows' }, [
firstEl,
prevEl,
paginationSummary,
nextEl,
lastEl,
]),
);
} else {
paginationEl.innerHTML = '<h5>No results.</h5>';
paginationEl.append(createTag('h5', { id: 'mmm-pagination-no-results' }, 'No results'));
}
el.append(paginationEl);
}

function handlePaginationDropdownChange() {
const paginationEl = document.querySelector('#mmm-pagination');
paginationEl?.querySelector('select')?.addEventListener('change', (event) => {
paginationEl.dataset.perpage = event.target.value;
filterPageList(
paginationEl.dataset.pageNum,
paginationEl.dataset.perpage,
event,
);
});
}

function handlePaginationClicks() {
const paginationEl = document.querySelector('#mmm-pagination');
paginationEl?.querySelectorAll('a').forEach((item) => {
item?.addEventListener('click', () => {
item.parentNode.setAttribute('data-current-page', item.getAttribute('data-page-num'));
filterPageList(item.getAttribute('data-page-num'));
item?.addEventListener('click', (event) => {
paginationEl.dataset.currentPage = item.dataset.pageNum;
filterPageList(
item.dataset.pageNum,
paginationEl.dataset.perpage,
event,
);
});
});
}
Expand Down Expand Up @@ -388,11 +441,12 @@ async function createPageList(el, search) {
el.replaceWith(mmmElContainer);
main.append(section);
createPaginationEl({
el: mmmElContainer,
data: response,
el: mmmElContainer,
});
paginationEl?.classList.remove('mmm-hide');
handlePaginationClicks();
handlePaginationDropdownChange();
}

/**
Expand Down

0 comments on commit fd41709

Please sign in to comment.