Creating pages containing grids I'm making an app that creates pdfs of images layed out in a grid. I know the size of each grid element and how many fit on a page, it works out to a 5x6 grid.
The syntax is not the real focus, but the logic for how I determine when to start a new row or page.

const pageconstants = {
 grid:{
   x: 5,
   y: 4,
 }
}

const griditems = []//an array containing 35 elements


const doc = new PDFDocument(
    {
        layout : 'portrait',
        width: 612,
        height: 792,
        autoFirstPage: false
    }
);

let gridx = 0;
let gridy = 0;
let pagenum = 1;

createNewPage(doc);//create new page and elements like header and footer

griditems.forEach((item) =&gt; {
    var x = 100 * gridx;//The actual equation has more parts, I'm simplifying here
    var y = 100 * gridy;

    addGridItem(doc, { x: x, y: y }, item)//places the image on the grid

    if( gridx == pageconstants.grid.x ){
      gridx = 0;

      if( gridy == pageconstants.grid.y ){
        subjecty = 0;
        pagenum++;
        createNewPage(doc)
      }
      else{
        subjecty++;
      }         
    }
    else{
      subjectx++;
    }
})


So basically, it checks if the current gridx has reached the max of 5 (6 because it starts at zero), and if so, resets gridx, and increments gridy to start the next row.

If gridy reaches it's maximum, gridx and gridy are reset and a new page is created again, so it can go again until there are no items left.
This all works, but it feels really word, I really hate having nested if's like this, and incrementing all these numbers. Is there a more elegant way to achieve this?
So essentially, you want to layout an array of items in a 2D grid. This problem can be solved by using division and remainder operations to calculate the coordinates.


x is the remainder of dividing the index by maxX
y is the remainder of dividing by maxY the result of dividing the index by maxX.
A new page made is when both x and y are 0


Here's a rough sketch of how it looks:

let i = item index
let maxX = 5
let maxY = 6
let x = i % maxX 
let y = (i / maxX) % maxY 
let p = !(i % (maxX * maxY))

i: 0 1 2 3 4 5 6 7 8 9 ... 29 30 31 32 33 34 35
x: 0 1 2 3 4 0 1 2 3 4 ... 4  0  1  2  3  4  0
y: 0 0 0 0 0 1 1 1 1 1 ... 5  0  0  0  0  0  1
p: 1 0 0 0 0 0 0 0 0 0 ... 0  1  0  0  0  0  0


In code, this would be:

const griditems = []

const pageconstants = {
 grid:{
   x: 5, // 5 across
   y: 6, // 6 down
 }
}

const doc = new PDFDocument({
  layout : 'portrait',
  width: 612,
  height: 792,
  autoFirstPage: false
})

const getX = i =&gt; i % pageconstants.grid.x
const getY = i =&gt; Math.floor((i / pageconstants.grid.x) % pageconstants.grid.y)
const isNewPage = i =&gt; !(i % (pageconstants.grid.x * pageconstants.grid.y))

const positions = griditems.forEach((item, index) =&gt; {
  const x = 100 * getX(index)
  const y = 100 * getY(index)

  if (isNewPage(index)) createNewPage(doc)

  addGridItem(doc, { x, y }, item)
})