I need to create a sequence of numbers for pagination links, this sequence needs to be 7 numbers in length and start 3 numbers before the given number and end 3 numbers after the given number so if the current page was 17 the sequence would be,
14, 15, 16, 17, 18, 19, 20
I have this working with the following code,
const range = (start, stop) => Array.from({ length: (stop - start)}, (_, i) => start (i*1));
But this code requires me to send the start and stop points, if I do this when the current page is <=3 I drop into minus numbers to get the sequence, when in reality would I would want is a sequence like,
3, 4, 5, 6, 7, 8, 9
so it's still 7 numbers in length, but because it couldn't do 3 preceeding number becaue it would start at 0 or lower it just did 7 proceeding numbers instead.
Is there a way in Jascript to work this stuff out, without a whole load of If/Else conditionals?
CodePudding user response:
Just derive start & stop from the page number (x
in the example below) using whatever logic you would like. Something like:
const range = (x) => {
const start = Math.max(1,x-3);
const stop = start 7;
return Array.from({ length: (stop - start)}, (_, i) => start i);
}
for(let i=1;i<20;i ){
console.log(i," -->", range(i).join(", "))
}
CodePudding user response:
A single if-else statement shouldn't be that bad. Here's a function getPages
where you pass in the current page number and it generates a range of pages according to your description.
function getPages(n) {
if (n > 3) {
return [n - 3, n - 2, n - 1, n, n 1, n 2, n 3];
} else {
return [n, n 1, n 2, n 3, n 4, n 5, n 6];
}
}
console.log(getPages(1))
console.log(getPages(3))
console.log(getPages(4))
console.log(getPages(17))
CodePudding user response:
Here's an example using the ternary operator to keep it one line, but you could use a simple if/else if you find it more readable
let pageNumber = 17;
const range = (pageNumber) => Array.from({length: 7}, (_, i) => pageNumber < 4 ? i 1 : i (pageNumber - 3))
console.log(range(pageNumber))
pageNumber = 3
console.log(range(pageNumber))
CodePudding user response:
I may have gone a bit far but, that being said, one approach is as below with explanatory comments in the code:
// a simple function to create new elements, with Object.assign() to set their properties:
const create = (tag, props) => Object.assign(document.createElement(tag), props),
// an arrow function that takes two numbers:
// startNumber: the number that should normally be in the centrepoint of the range,
// and the size of the range itself, these both have default values (adjust as required):
generateRange = (startNumber = 5, range = 7) => {
// here we find the minimum value, by taking the supplied (or default) startNumber
// and subtracting the floored result of the range divided by 2:
let minValue = startNumber - Math.floor(range / 2);
// if that minimum value is less than 1:
if (minValue < 1) {
//we set the minimum value to 1:
minValue = 1;
}
// creating the Array of numbers:
let baseRange = Array.from({
// setting the length of the created Array:
length: 7
}).map(
// passing in the index of the current array-element,
// and adding the current index to the supplied minValue:
(_, i) => i minValue);
// returning the created range:
return baseRange;
}
// iterating over the collection of <li> elements in the document,
// using NodeList.prototype.forEach():
document.querySelectorAll('li').forEach(
// passing the current <li> element, and the index of that
// element, to the function body:
(el, i) => {
// adding 1 to the zero-based index (this is - admittedly -
// entirely unnecessary, but I did it anyway):
let rangeStartValue = i 1;
// appending a created <span> to the current <li>
el.append(create('span', {
// setting the textContent of that <span>:
textContent: rangeStartValue
}));
// creating a range of numbers, passing the rangeStartValue,
// and iterating over the resulting Array using Array.prototype.forEach():
generateRange(rangeStartValue).forEach(
// passing the current array-element (an integer):
(rangeValue) => {
// for each element we append a created <a> element:
el.append(
create('a', {
// with its textContent set to the current array-element value:
textContent: rangeValue,
// setting the href property of the element to a fragment identifier
// followed by the current array-element value:
href: `#${rangeValue}`,
// if the current rangeValue is exactly equal to the rangeStartValue,
// we add the class-name of 'current', otherwise we add an empty string
// (which results in the 'class' attribute being present, but containing
// no class-names:
className: rangeValue === rangeStartValue ? 'current' : 'other'
})
);
});
});
li {
display: flex;
flex-flow: row wrap;
justify-content: space-between;
gap: 0.5rem;
margin-block: 0.25em;
}
span {
flex-basis: 100%;
}
span::before {
content: 'Starting at ';
}
span::after {
content: ': ';
}
a {
border: 1px solid currentColor;
color: rebeccapurple;
flex-basis: 3em;
flex-grow: 1;
padding: 0.5rem;
text-align: center;
}
.current {
background-color: skyblue;
color: white;
}
<ol>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ol>
References:
Array.prototype.forEach()
.- Arrow functions.
Document.createElement()
.Document.querySelectorAll()
.Element.append()
.NodeList.prototype.forEach()
.Node.textContent
.
CodePudding user response:
i think this is the most easy way, it will not use start from 1
for any number less than 4 then it will increase after 4
to use 3nums before and 3 after
try to enter any number and click generate
let btn = document.querySelector('input[type="button"]')
let rslt = document.querySelector('div#result')
let elm = document.querySelector('input[type="text"]')
let before= [], after = []
const getSerial = (n) => {
before = []
after = []
let beforeNum = parseInt(n)-4
let afterNum = parseInt(n)
for(let i=1;i<4;i ){
before.push(beforeNum i)
after.push(afterNum i)
}
}
btn.addEventListener('click', () => {
let num = parseInt(elm.value)
while( num <= 3) {
num = 4
}
getSerial(parseInt(num))
let result = before.concat(parseInt(num)).concat(after)
rslt.innerHTML = result.toString().replaceAll(',',' ')
})
<input type="text" />
<input type="button" value="generate" />
<div id="result"></div>