sensation
sensation

Reputation: 437

Break UL tag after 'n' times in while-loop

I'm currently in developing module shop for the company I work for and there is a little problem. While extracting records from the table, I want for every third data record to close HTML "UL" tag.

This is what I currently have:

<?php
  $selektKat = "SELECT * FROM `proizvodi` WHERE `kategorija` = '$kat'"; //don't worry about SQLi; I will fix it
  $result = mysqli_query($con, $selektKat) or die(mysqli_error());

// Line where the loop starts
<?php
while ($row = mysqli_fetch_array($result)) { ?>

  <ul class="products-grid clearfix" style="margin-right: 5px; margin-left: 20px;">
  <li class="item" style="min-height: 339px">
    <a id="product-image-42321" href="proizvod.php" title="naziv" class="product-image">
      <img src="http://static.511tactical.com/mag/media/catalog/product/cache/1/small_image/220x/9df78eab33525d08d6e5fb8d27136e95/5/3/53212_716_Alternate1.jpg" width="220" alt="<?php echo $row['naziv'] ?>" />
    </a>
      <ul class="swatches clearfix">
      <li id="swatch-228" class="swatch product-42321">
        <a href="proizvod.php" title="<?php echo $row['naziv']; ?>">
        <img src="<?php echo __DIR__ . '/images/' . $row['slika'] . '.jpg'; ?>" />
        </a>
      </li>
      </ul>

      <div class="price-box">
        <span class="label" id="configurable-price-from-42321">
          <span class="configurable-price-from-label">
          </span>
        </span>


      <div class="product-name"><a id="product-name-140981" href="proizvod.php"><?php echo $row['naziv']; ?></a></div>

      <span class="regular-price" id="product-price-42321">
        <span class="price"><?php echo $row['cijena']; ?><sup>KM</sup>
        </span>
      </span>
      </div>

      <div class="actions">
      </div>

  </li>

<?php
}
?>
</ul> // This has to be closed in loop after every 3 records
</div>

Picture: enter image description here

Cheers.

Upvotes: 3

Views: 2937

Answers (5)

giorgio
giorgio

Reputation: 10202

You specifically ask for opening and closing <ul> tags, but may I suggest an alternative, using only css, which can be easily converted into a responsive solution?

To start with, just put your items in a div instead of an list item (omitting the <ul> altogether):

<div class="product-grid">
    <?php while ( $row = mysqli_fetch_array( $result ) ): ?>
        <div class="item"> ... </div>
    <?php endwhile; ?>
</div>

Now just use plain old css to float the grid and add margins in between the columns. Then using the nth-of-type pseudo-selector we can clear the margin on the nth element, depending on how many items you want in a row.

Always-3-column-grid example (Fiddle)

.product-grid { width: 100%; }
.product-grid .item { float: left; width: 32%; margin-left: 2%; margin-bottom: 2%; }
.product-grid .item:nth-of-type(3n+1) { margin-left: 0; }

Now the items are placed nicely in a grid, and it doesn't matter at all how wide the container is.

Fiddle note: the overflow: hidden is a kind of clearfix to show the border. It also works without it.

Now if you want, for instance, add breakpoints to show a 2-column grid instead of a 3-column grid on smaller devices, just change the width of the item and the counter of the pseudo selector. I've put the 3-grid counter in a media query as well, so you don't have to overwrite that one.

3-to-2-column-grid example (Fiddle)

Don't forget to resize the example panel to see the responsive result ;)

.product-grid { width: 100%; }
.product-grid .item { float: left; width: 32%; margin-left: 2%; margin-bottom: 2%; }

/* 3-column */
@media (min-width: 501px) {
    .product-grid .item:nth-of-type(3n+1) { margin-left: 0; }
}

/* 2-column. Don't forget to alter the item width accordingly */
@media (max-width: 500px) {
    .product-grid .item { width: 49%; }
    .product-grid .item:nth-of-type(2n+1) { margin-left: 0; }
}

And here you go! Your fully responsive 3-to-2-column grid :) Just alter the breakpoints to your needs, and the width and margin sizes (just to make sure that in a 3-column version 3*columnWidth + 2*marginWidth adds up to 100%, and 2*columnWidth + marginWidth for the 2-column version).

Upvotes: 1

Marcin Nabiałek
Marcin Nabiałek

Reputation: 111839

First, I provide simple PHP script that can be addapted to your needs. In this script open and end tags are handled properly.

I added also $break_after variable - you can set here any positive value you want - in your case it's 3 because you want to do the action after each 3rd element.

First method (it assumes you can get number of data elements before loop)

<?php
$data = array(1,2,3,4,5);

$break_after = 3;

$counter = 0;   
$totalNumber = count($data);                    
foreach ($data as $item) {
    if ($counter % $break_after == 0) {
        echo '<ul>';
    }
    echo '<li>'.$item.'</li>';    

    if ($counter % $break_after == ($break_after-1) || $counter == $totalNumber-1) {
        echo '</ul>';
    }
    ++$counter;

}

Second method (it assumes you cannot get number of data elements before loop)

<?php
$data = array(1,2,3,4,5);

$break_after = 3;

$counter = 0;               
foreach ($data as $item) {
    if ($counter % $break_after == 0) {
        echo '<ul>';
    }
    echo '<li>'.$item.'</li>';    

    if ($counter % $break_after == ($break_after-1)) {
        echo '</ul>';
    }
    ++$counter;

}

if ((($counter-1) % $break_after) != ($break_after-1)) {
    echo '</ul>';

}

Regarding your question, you also need to remember to start your <ul> each 3rd record (not just closing it) but also make sure to close it after your loop. In your case you can use second method because you don't know number of elements (in fact you can get them using mysqli_num_rows function and then you could also use method 1). For your case your code should probably look like this:

<?php
  $selektKat = "SELECT * FROM `proizvodi` WHERE `kategorija` = '$kat'"; //don't worry about SQLi; I will fix it
  $result = mysqli_query($con, $selektKat) or die(mysqli_error());

// Line where the loop starts
<?php
$counter = 0;   

$break_after = 3;

while ($row = mysqli_fetch_array($result)) { 
  if ($counter % $break_after == 0) {
   ?>
  <ul class="products-grid clearfix" style="margin-right: 5px; margin-left: 20px;">
  <?php } ?>
  <li class="item" style="min-height: 339px">
    <a id="product-image-42321" href="proizvod.php" title="naziv" class="product-image">
      <img src="http://static.511tactical.com/mag/media/catalog/product/cache/1/small_image/220x/9df78eab33525d08d6e5fb8d27136e95/5/3/53212_716_Alternate1.jpg" width="220" alt="<?php echo $row['naziv'] ?>" />
    </a>
      <ul class="swatches clearfix">
      <li id="swatch-228" class="swatch product-42321">
        <a href="proizvod.php" title="<?php echo $row['naziv']; ?>">
        <img src="<?php echo __DIR__ . '/images/' . $row['slika'] . '.jpg'; ?>" />
        </a>
      </li>
      </ul>

      <div class="price-box">
        <span class="label" id="configurable-price-from-42321">
          <span class="configurable-price-from-label">
          </span>
        </span>


      <div class="product-name"><a id="product-name-140981" href="proizvod.php"><?php echo $row['naziv']; ?></a></div>

      <span class="regular-price" id="product-price-42321">
        <span class="price"><?php echo $row['cijena']; ?><sup>KM</sup>
        </span>
      </span>
      </div>

      <div class="actions">
      </div>

  </li>

<?php
    if ($counter % $break_after == ($break_after - 1)) {
        echo '</ul>';
    }
    ++$counter;

}

if (($counter-1) % $break_after != ($break_after - 1)) { // make sure there will be closing </ul>
    echo '</ul>';

}
?>
</div>

Upvotes: 7

Brotheryura
Brotheryura

Reputation: 1188

<?php
//Our images
$array = array(1,2,3,4,5,6,7,8,9,10,11,12,13,14);
//Count array for last ul
$count_array = count($array);
//Counter
$count       = 0;
foreach ($array as $key => $value) {
    $count++;
    //Begin
    if ($count % 3 == 1) {
        echo '<ul>';
    }
    //Output data
    echo '<li>' . $value . '</li>';
    //Close ul
    if ($count % 3 == 0 || $count_array == $count) {
        echo '</ul>';
    }
}
?>

Output:

<ul><li>1</li><li>2</li><li>3</li></ul><ul><li>4</li><li>5</li><li>6</li></ul><ul><li>7</li><li>8</li><li>9</li></ul><ul><li>10</li><li>11</li><li>12</li></ul><ul><li>13</li><li>14</li></ul>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

Upvotes: 1

Valentin Mercier
Valentin Mercier

Reputation: 5326

Add a varaible, let's say $i in you while that you increment at each iteration. And when it is a multiple of 3, just close your ul.

while ($row = mysqli_fetch_array($result)) {

    // YOUR CODE HERE

    $count++;
    if ($count % 3 == 0) echo '</ul>';
}

For the record the %operator will give you the remainder of the euclidean division.

Upvotes: -2

Caweren
Caweren

Reputation: 244

$i=0;
while ($row = mysqli_fetch_array($result)) { 

// Your code

if($i % 5 == 0){ // Break </ul> tag here}

// Rest of code


$i++;
} // End while loop

the % is modulus, it returns the remainder after a division is done, so

5 % 5 = 0 9 % 5 = 4

Upvotes: -1

Related Questions