Skip to main content
Print

Pagination with Divi 5 Loop

Step by Step guideline to add pagination in Divi 5 Loop layout:

Step 1: Setup the loop layout. Make sure to label the loop item properly, so that we can target that through the pagination module.

Step 2: Add the Pagination module and select the loop that you want to connect. No class/ID needed for this procedure.

Step 3: Paste the script from the attached file in script.js file.

Step 4: Paste the CSS from attached file in style.css file.

Now the pagination is ready with the AJAX. It will work dynamically.

//pagination fix

document.addEventListener('DOMContentLoaded', function () {

    const selector = '.et_pb_posts_nav[data-target-loop]';
    let ajaxRunning = false;

    function getPage(url, loopId) {
        try {
            return parseInt(
                new URL(url, window.location.href).searchParams.get(loopId),
                10
            ) || 1;
        } catch (e) {
            return 1;
        }
    }

    function getItems(loopId, doc) {
        return Array.from(
            doc.querySelectorAll(
                '[data-loop-item][data-loop-source="' + loopId + '"]'
            )
        );
    }

    function bindAjax(link, pagination) {

        if (!link || link.dataset.ajaxBound === '1') {
            return;
        }

        link.dataset.ajaxBound = '1';

        link.addEventListener('click', function (e) {
            e.preventDefault();
            loadPage(pagination, link.href);
        });
    }

    function updatePagination(pagination, source, currentPage) {

        const loopId = pagination.dataset.targetLoop;

        const sourcePrev = source.querySelector('.nav-previous a');
        const sourceNext = source.querySelector('.nav-next a');

        /*
         * Create Previous container if it does not exist
         */
        let prevBox = pagination.querySelector('.nav-previous');

        if (!prevBox && sourcePrev) {

            prevBox = document.createElement('span');
            prevBox.className = 'nav-previous';

            prevBox.innerHTML =
                '<a href="' + sourcePrev.href + '">' +
                    '<span class="meta-nav">← </span>' +
                    '<span class="nav-label">Previous</span>' +
                '</a>';

            pagination.insertBefore(
                prevBox,
                pagination.firstChild
            );
        }

        /*
         * Update Previous
         */
        if (prevBox) {

            if (sourcePrev) {

                const prevLink = prevBox.querySelector('a');

                if (prevLink) {
                    prevLink.href = sourcePrev.href;
                }

                prevBox.style.display = '';
                bindAjax(prevLink, pagination);

            } else {

                prevBox.style.display = 'none';
            }
        }

        /*
         * Create Next container if needed
         */
        let nextBox = pagination.querySelector('.nav-next');

        if (!nextBox && sourceNext) {

            nextBox = document.createElement('span');
            nextBox.className = 'nav-next';

            nextBox.innerHTML =
                '<a href="' + sourceNext.href + '">' +
                    '<span class="nav-label">Next</span>' +
                    '<span class="meta-nav"> →</span>' +
                '</a>';

            pagination.appendChild(nextBox);
        }

        /*
         * Update Next
         */
        if (nextBox) {

            if (sourceNext) {

                const nextLink = nextBox.querySelector('a');

                if (nextLink) {
                    nextLink.href = sourceNext.href;
                }

                nextBox.style.display = '';
                bindAjax(nextLink, pagination);

            } else {

                nextBox.style.display = 'none';
            }
        }

        /*
         * Remove old page numbers
         */
        const oldNumbers =
            pagination.querySelector('.custom-page-numbers');

        if (oldNumbers) {
            oldNumbers.remove();
        }

        /*
         * Create page numbers
         */
        const numbers = document.createElement('span');
        numbers.className = 'custom-page-numbers';

        function addNumber(page, url, current) {

            const link = document.createElement('a');

            link.href = url || '#';
            link.textContent = page;
            link.className = 'custom-page-number';

            if (current) {

                link.classList.add('current');
                link.setAttribute('aria-current', 'page');

            } else {

                bindAjax(link, pagination);
            }

            numbers.appendChild(link);
        }

        /*
         * Previous page number
         */
        if (currentPage > 1 && sourcePrev) {

            addNumber(
                currentPage - 1,
                sourcePrev.href,
                false
            );
        }

        /*
         * Current page
         */
        addNumber(
            currentPage,
            null,
            true
        );

        /*
         * Next page number
         */
        if (sourceNext) {

            const nextPage = getPage(
                sourceNext.href,
                loopId
            );

            addNumber(
                nextPage,
                sourceNext.href,
                false
            );
        }

        /*
         * Insert numbers between Previous and Next
         */
        if (nextBox) {

            pagination.insertBefore(
                numbers,
                nextBox
            );

        } else {

            pagination.appendChild(numbers);
        }
    }

    function replaceItems(pagination, newDoc) {

        const loopId = pagination.dataset.targetLoop;

        const oldItems = getItems(loopId, document);
        const newItems = getItems(loopId, newDoc);

        if (!oldItems.length || !newItems.length) {
            return false;
        }

        const parent = oldItems[0].parentElement;

        if (!parent) {
            return false;
        }

        const fragment = document.createDocumentFragment();

        newItems.forEach(function (item) {
            fragment.appendChild(
                item.cloneNode(true)
            );
        });

        oldItems.forEach(function (item) {
            item.remove();
        });

        parent.appendChild(fragment);

        return true;
    }

    function loadPage(pagination, url) {

        if (ajaxRunning) {
            return;
        }

        ajaxRunning = true;

        pagination.classList.add(
            'pagination-loading'
        );

        fetch(url, {
            method: 'GET',
            credentials: 'same-origin'
        })
        .then(function (response) {

            if (!response.ok) {
                throw new Error();
            }

            return response.text();
        })
        .then(function (html) {

            const doc =
                new DOMParser().parseFromString(
                    html,
                    'text/html'
                );

            const loopId =
                pagination.dataset.targetLoop;

            const newPagination =
                doc.querySelector(
                    '.et_pb_posts_nav[data-target-loop="' +
                    loopId +
                    '"]'
                );

            if (!newPagination) {
                window.location.href = url;
                return;
            }

            if (!replaceItems(pagination, doc)) {
                window.location.href = url;
                return;
            }

            const currentPage =
                getPage(url, loopId);

            updatePagination(
                pagination,
                newPagination,
                currentPage
            );

            window.history.pushState(
                {
                    loopPage: currentPage
                },
                '',
                url
            );

            const firstItem =
                getItems(loopId, document)[0];

            if (firstItem) {

                window.scrollTo({
                    top:
                        firstItem.getBoundingClientRect().top +
                        window.pageYOffset -
                        100,
                    behavior: 'smooth'
                });
            }

        })
        .catch(function () {

            window.location.href = url;

        })
        .finally(function () {

            ajaxRunning = false;

            pagination.classList.remove(
                'pagination-loading'
            );
        });
    }

    function initialize(pagination) {

        const loopId =
            pagination.dataset.targetLoop;

        if (!loopId) {
            return;
        }

        updatePagination(
            pagination,
            pagination,
            getPage(
                window.location.href,
                loopId
            )
        );
    }

    document
        .querySelectorAll(selector)
        .forEach(function (pagination) {
            initialize(pagination);
        });

    /*
     * Browser Back / Forward
     */
    window.addEventListener('popstate', function () {

        document
            .querySelectorAll(selector)
            .forEach(function (pagination) {

                loadPage(
                    pagination,
                    window.location.href
                );

            });
    });

});


/**Pagination fix**/
body #page-container .et_pb_posts_nav,
body #page-container .et_pb_posts_nav .custom-page-numbers,
body #page-container .et_pb_posts_nav .custom-page-number,
body #page-container .et_pb_posts_nav .custom-page-prev{
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
}

body #page-container .et_pb_posts_nav .nav-next {
    margin-left: unset;
}
body #page-container .et_pb_posts_nav a{
    padding: 12px 10px;
    border: 1px solid;
    line-height: 1em;
	width: 40px;
    height: 40px;
	transition: all .3s ease;
}
body #page-container .et_pb_posts_nav a:hover,
body #page-container .et_pb_posts_nav a.current{
    background: #10512a;
    color: #fff !important;
	border: 1px solid #10512a;
}
body #page-container .et_pb_posts_nav a:hover > .meta-nav{
    color: #fff !important;
}
body #page-container .et_pb_posts_nav a .meta-nav,
body #page-container .et_pb_posts_nav .nav-label{
    display: none;
}
body #page-container .et_pb_posts_nav .nav-previous a,
body #page-container .et_pb_posts_nav .nav-next a{
    position: relative !important;
    margin: 0 !important;
    display: flex;
}
body #page-container .et_pb_posts_nav .nav-previous a:before,
body #page-container .et_pb_posts_nav .nav-next a:before{
    content: "\34";
    font-family: ETmodules;
    color: #10512a;
    line-height: 1em !important;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    color: inherit;
}
body #page-container .et_pb_posts_nav .nav-next a:before{
    content: "\35";
}
@media (max-width: 980px){
	body #page-container .et_pb_posts_nav a{
		height: 35px;
		width: 35px;
	}
}

Table of Contents