2

I'm trying to loop through an array of items and build up a HTML structure based on what count we are at through the array.

It should wrap every item in a cell and every 4 items in a row and every 8 items in a column div.

Here is the JavaScript:

var html = ''; // for those that were asking where html was...

for(var i=0;i<response.length;i++)
{
     // for first and every 8 items
     if(i == 0 || i % 8 === 0)
    {
        console.log('columnstart');
        html = html + '<div class="column">';
    }

    //  for first and every 4 items
    if(i == 0 || i % 5 === 0)
    {
        console.log('rowstart');
        html = html + '<div class="row">';
    }

    // after every 4 items BUT NOT the first
    if(i % 4 === 0 && i !== 0) 
    {
        console.log('rowend');
        html = html + '</div>';
    }

    // after every 8 items BUT NOT the first
    if(i == response.length && i !== 0 || i % 7 === 0 && i !== 0)
    {
        console.log('columnend');
        html = html + '</div>';
    }

    console.log('cell');
    html = html + '<div class="cell"></div>';
}

and here is an example of how the HTML should be being rendered:

<div class="column">
    <div class="row">
        <div class="cell"></div>
        <div class="cell"></div>
        <div class="cell"></div>
        <div class="cell"></div>
    </div>
    <div class="row">
        <div class="cell"></div>
        <div class="cell"></div>
        <div class="cell"></div>
        <div class="cell"></div>
    </div>
</div>
<div class="column">
    <div class="row">
        <div class="cell"></div>
        <div class="cell"></div>
        <div class="cell"></div>
        <div class="cell"></div>
    </div>
    <div class="row">
        <div class="cell"></div>
        <div class="cell"></div>
        <div class="cell"></div>
        <div class="cell"></div>
    </div>
</div>

However it seems my counts are off...

Because I get the following in the console:

columnstart
rowstart
cell
cell
cell
cell
cell
rowend
rowstart
cell
cell
cell
columnend
columnstart
cell
rowend
cell
rowstart
cell
cell
2
  • Where is html declared? You should declare it as var html = '' and then instead of html = html + something you can use html += something. It's important that when you declare html you set it equal to an empty string, otherwise you end up with undefined at the beginning of your html string which can cause errors when the browser tries to parse it. Commented Jun 23, 2015 at 16:06
  • @Brian It's kind of assumed that I have declared the html variable as this loop is part of some larger logic but the rest of the code isn't relevant to the question. Commented Jun 23, 2015 at 16:12

5 Answers 5

2

Well, it seems there was a lot wrong with your logic, so I just rewrote the whole thing. Basically, treat the first and last element as special cases, that way the counting logic doesn't need to be as complicated.

See comments for more information:

var html = '';

for (var i = 0; i < response.length; i++) {
    // If first element, open column and row and add first cell.
    if (i == 0) {
        html = html + '<div class="column">';
        html = html + '<div class="row">';
        html = html + '<div class="cell"></div>';

        // If the first element, is also the last, then close row and column now.
        if (i == response.length - 1) {
            html = html + '</div>';
            html = html + '</div>';
        }
    }
    // If last element, add last cell and close row and column.
    else if (i == response.length - 1) {
        html = html + '<div class="cell"></div>';
        html = html + '</div>';
        html = html + '</div>';
    }
    // Otherwise, process based on count.
    else {
        // If end of row, then close row.
        if (i % 4 == 0) {
            html = html + '</div>';
        }

        // If end of column close column, open new column.
        if (i % 8 == 0) {
            html = html + '</div>';
            html = html + '<div class="column">';
        }

        // If end of row, open new row.
        if (i % 4 == 0) {
            html = html + '<div class="row">';
        }

        // Insert the cell.
        html = html + '<div class="cell"></div>';
    }
}

Here is a working example

Sign up to request clarification or add additional context in comments.

1 Comment

I have just modified the code so it works with only a single element too
0

A couple of tyypos:

//  for first and every 4 items
if(i == 0 || i % 5 === 0)
{
    console.log('rowstart');
    html = html + '<div class="row">';
}

should be:

//  for first and every 4 items
if(i == 0 || i % 4 === 0)
{
    console.log('rowstart');
    html = html + '<div class="row">';
}

a typpo or two and an issue with logic and precedence:

// after every 8 items BUT NOT the first
if(i == response.length && i !== 0 || i % 8 === 0 && i !== 0)
{
    console.log('columnend');
    html = html + '</div>';
}

should be:

// after every 8 items BUT NOT the first
if(i === response.length - 1 || (i !== 0 && i % 8 === 0))
{
    console.log('columnend');
    html = html + '</div>';
}

3 Comments

Using your code I get: columnstart (index):612 rowstart 4(index):632 cell (index):612 rowstart (index):619 rowend 4(index):632 cell (index):605 columnstart (index):612 rowstart (index):619 rowend (index):626 columnend 4(index):632 cell so it's still incorrect...
@Cameron: I'm not sure what your output there means. Where are the numbers coming from in the code above?
@Cameron: Besides, at this point you know enough about what the issues are to finish writing your code yourself. :P
0
for(var i=0;i<response.length;++i)
{
     // for first and every 8 items
     if(i % 8 == 0) {
         console.log('columnstart');
         html = html + '<div class="column">';
     }

     //  for first and every 4 items
     if(i % 4 == 0) {
         console.log('rowstart');
         html = html + '<div class="row">';
     }

     console.log('cell');
     html = html + '<div class="cell"></div>';

     // after every 4 items BUT NOT the first
     if(i % 4 == 3) {
         console.log('rowend');
         html = html + '</div>';
     }

     // after every 8 items
     if(i % 8 == 7) {
         console.log('columnend');
         html = html + '</div>';
     }
}

1 Comment

Of course this assumes that response.length is always a multiple of 8.
0

Should be

for(var i=0;i<response.length;i++)
{
 // Before 1st and every 8 cells
 if(i % 8 == 0)
{
    console.log('columnstart');
    html = html + '<div class="column">';
}

//  Before 1st and every 4 items
if(i % 4 == 0)
{
    console.log('rowstart');
    html = html + '<div class="row">';
}

console.log('cell');
html = html + '<div class="cell"></div>';

// after every 4th cell added
if(i % 4 == 3) 
{
    console.log('rowend');
    html = html + '</div>';
}

// after every 8th cell added
if(i % 8 ==7)
{
    console.log('columnend');
    html = html + '</div>';
}


}

4 Comments

that last if statement still doesn't work that way.
I think the other clause is still necessary. The comment should read, "after every 8 items BUT NOT the first, OR it's the last item".
That's what I'd thought initially, but the loop ends before then - the for statement has i<response.length so no need to ensure i != response.length
My previous answer was incorrect - I had edited the modulos based on the comments near them, but not what the OP was trying to do. Should be corrected now to match the desired output.
0

I'm afraid you misinterpreted the modulo (%) operator

i % 7==0 means that i is divisible by 7 what you want is i % 8==7

I always find it more clear with a switch statement:

while (response.length%8!=7)
    response.push('');
var html='';
for(var i=0;i<response.length;i++)
{
    switch (i%8) {
        case 0:  html = html + '<div class="column"><div class="row">'+response[i];break;
        case 4:  html = html + '</div><div class="row">'+response[i];break;
        case 7:  html = html + response[i]+'</div></div>';break;
        default: html = html + response[i];
    }
}

1 Comment

Not quite. The comment should read, "after every 8 items BUT NOT the first, OR it's the last item"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.