Nice Paging Steps

Bert's algorithm to get the page numbers for the pagination dropdown, ported from Java to JavaScript

by Torsten Walter

HTML

<label for="currentPageNumber">current page number (0 based)</label>
<input name="currentPageNumber" type="number" value="9">
<br>
<label for="numPages">number of pages</label>
<input name="numPages" type="number" value="20">
<br>
<button id="calculate">calculate</button>
<hr>
<h3>Result</h3>
<pre id="result">No result yet, click “calculate”</pre>

JavaScript

const NICE_PAGING_STEPS = [1000, 500, 200, 100, 50, 20, 10, 5];

function applyNiceStepsToFirstPages(pageNumbers) {
    let firstPageNumber = pageNumbers[0] + 1;
    let start = -1;
    let step = 1;
    for (let startCandidate = 3; startCandidate <= 5; ++startCandidate) {
        const stepCandidate = NICE_PAGING_STEPS.find(candidate => {
        		let temp = pageNumbers[startCandidate + 1] - pageNumbers[startCandidate + 1] % candidate - 1;
            let page1 = temp - (startCandidate - 1) * candidate;
            return page1 > firstPageNumber && candidate >= step;
        });
        if (stepCandidate) {
        	start = startCandidate;
          step = stepCandidate;
        }
        /*for (let stepCandidate of NICE_PAGING_STEPS) {
            let temp = pageNumbers[startCandidate + 1] - pageNumbers[startCandidate + 1] % stepCandidate - 1;
            let page1 = temp - (startCandidate - 1) * stepCandidate;
            if (page1 > firstPageNumber && stepCandidate >= step) {
                start = startCandidate;
                step = stepCandidate;
                break;
            }
        }*/
    }
    if (step > 1) {
        pageNumbers[start] = pageNumbers[start + 1] - pageNumbers[start + 1] % step - 1;
        for (let i = start - 1; i >= 1; --i) {
            pageNumbers[i] = pageNumbers[i + 1] - step;
        }
    }
}

function applyNiceStepsToLastPages(pageNumbers) {
    let lastPageNumber = pageNumbers[18];
    let start = -1;
    let step = 1;
    for (let startCandidate = 15; startCandidate >= 13; --startCandidate) {
        for (let stepCandidate of NICE_PAGING_STEPS) {
            let temp = (pageNumbers[startCandidate - 1] + 2) - ((pageNumbers[startCandidate - 1] + 2) % stepCandidate) - 1 + stepCandidate;
            let page17 = temp + (17 - startCandidate) * stepCandidate;
            if (page17 < lastPageNumber && stepCandidate >= step) {
                start = startCandidate;
                step = stepCandidate;
               ...