Jari Rengeling
Jari Rengeling

Reputation: 9

Reset loop after 4 times

I am looping products on my page and the background-color goes as follow:
'transparent' - 'grey' - 'transparent' - 'grey'

There are 4 products on each row but when the second row starts it is doing the same order like:
Situation 1 - Wrong situation
'transparent' - 'grey' - 'transparent' - 'grey'
'transparent' - 'grey' - 'transparent' - 'grey'

But I want it like:
Situation 2 - Correct situation
'transparent' - 'grey' - 'transparent' - 'grey'
'grey' - 'transparent' - 'grey' - 'transparent'

Does anyone know how to edit my loop to get the structure as above?

<div class="row page-margin pb-5">
    <?php
    $term = get_field('product_category'); if( $term ): $cat = esc_html( $term->slug ); endif;
    $args = array( 'post_type' => 'product', 'product_cat' => $cat);
    $loop = new WP_Query( $args );
    $product_id = get_the_id();
    $c = 0;
    $product = wc_get_product( $product_id );
    while ( $loop->have_posts() ) : $loop->the_post(); ?>
        <div class="col-md-3 pl-0 pr-0">
            <a href="<?php the_permalink(); ?>">
                <div class="product-list-item <?php if ($c & 1) { ?>bg-grey<?php } ?>">
                    <div class="img-wrapper">
                        <?php echo $product->get_image('full', array('class' => 'img-fluid')); ?>
                    </div>
                    <div class="product-content">
                        <span class="product-title"><?php echo $product->get_name(); ?></span>
                        <span class="product-price">€ <?php $price = $product->price; $price_incl_tax = $price + round($price * ( 0 / 100 ), 2); $price_incl_tax = number_format($price_incl_tax, 2, ",", "."); $price = number_format($price, 2, ",", "."); echo $price_incl_tax; ?> incl. BTW</span>
                    </div>
                </div>
            </a>
        </div>
    <?php $c++; endwhile; wp_reset_query(); // Remember to reset ?>
</div>

Here is an image of the wrong situation (Situation 1):
Wrong situation picture

Thanks for your time!

Upvotes: 0

Views: 177

Answers (3)

chriskirknielsen
chriskirknielsen

Reputation: 2929

No need to hardcode this into your template. Use CSS to achieve this with a slightly complex list of selectors. You can wrap this in a media query since I see you have col-md-3. Assuming you're using bootstrap, that would be @include media-breakpoint-up(md) you'd be using.

.container {
  display: flex;
  flex-wrap: wrap;
  background: gray;
}

.item {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 25%;
  height: 100px;
  background: white;
}

.item:nth-child(4n+2):not(:nth-child(8n-2)), /* 2, 10, 18… */
.item:nth-child(4n+4):not(:nth-child(8n)), /* 4, 12, 20… */
.item:nth-child(4n+1):not(:nth-child(8n+1)), /* 5, 13, 21… */
.item:nth-child(4n+3):not(:nth-child(8n+3)) { /* 7, 15, 23… */
  background: red;
}
<div class="container">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
  <div class="item">6</div>
  <div class="item">7</div>
  <div class="item">8</div>
  <div class="item">9</div>
  <div class="item">10</div>
  <div class="item">11</div>
  <div class="item">12</div>
  <div class="item">13</div>
  <div class="item">14</div>
  <div class="item">15</div>
  <div class="item">16</div>
  <div class="item">17</div>
  <div class="item">18</div>
  <div class="item">19</div>
  <div class="item">20</div>
</div>

Now to explain the selector logic: you want to target every 2nd and 4th child on odd rows, and the 1st and 3rd child on even rows. To do so, you target, respectively:

  • Every 2 items that aren't a multiple of 6
  • Every 4 items that aren't a multiple of 8
  • Every 5 items that aren't a multiple of 9
  • Every 7 items that aren't a multiple of 11

Hope this helps!

Upvotes: 1

Andreas
Andreas

Reputation: 23958

If you want it done in php the method I found working is to use two arrays which is out of sync with transparent and grey.
Then echo from one array on one row then switch.

It's not a nice code but it does the trick.

$arr1 = ['transparent', 'grey', 'transparent', 'grey'];
$arr2 = ['grey', 'transparent', 'grey', 'transparent'];


$i = 0;
$bool = true;
Your loop{
    if($bool){
        echo 'color ' . $arr1[$i] . "\n";
    }else{
        echo 'color ' . $arr2[$i] . "\n";
    }
    $i = ++$i % 4;
    if($i ==0) $bool = !$bool;
}

Here is a running example of the code:

https://3v4l.org/XdcHB

Upvotes: 0

nice_dev
nice_dev

Reputation: 17805

Ok this is a little tricky because you are changing the order of decision at the chunk of 4. To decide this, you can have an extra $flag variable which is initially set to false.

So, the check goes as:

if ($flag && ($c & 1) == 0 || !$flag && ($c & 1) == 1)

This says if we are at the odd iteration(when $flag is false) and current $c is odd or we at the even iteration(when $flag is true) and current $c is even.

We reset the flag when $c gets reinitialized to 0 indicating next row flip.

Snippet:

<?php

$c = 0;
$product = wc_get_product( $product_id );
while ( $loop->have_posts() ) : $loop->the_post(); ?>
        <div class="col-md-3 pl-0 pr-0">
            <a href="<?php the_permalink(); ?>">
                <div class="product-list-item <?php if ($flag && ($c & 1) == 0 || !$flag && ($c & 1) == 1) { ?>bg-grey<?php } ?>">
                    <div class="img-wrapper">
                        <?php echo $product->get_image('full', array('class' => 'img-fluid')); ?>
                    </div>
                    <div class="product-content">
                        <span class="product-title"><?php echo $product->get_name(); ?></span>
                        <span class="product-price">€ <?php $price = $product->price; $price_incl_tax = $price + round($price * ( 0 / 100 ), 2); $price_incl_tax = number_format($price_incl_tax, 2, ",", "."); $price = number_format($price, 2, ",", "."); echo $price_incl_tax; ?> incl. BTW</span>
                    </div>
                </div>
            </a>
        </div>
    <?php $c = ($c + 1) % 4; $flag = $c == 0 ? !$flag : $flag; endwhile; wp_reset_query(); // Remember to reset ?>

Upvotes: 0

Related Questions