I have an array of icons. Right now, we only display them in buckets of 4. So if you have 7 icons, the 4th icon on the first slide will repeat as the 8th on the second slide. That's because the 3rd index of the array is stored in that same spot. To fix this, I want to loop through the array instead of explicitly iterating icon by icon.
<?php if (!empty($icons)) { // if we have icons attributes
// NOTE: we've changed it to show as many sets as we can
// (sets of 4)
$number_of_sets = ceil(count($icons) / 4);
$k=0; // for inner iteration
for ($j=0;$j < $number_of_sets; $j++) {
$slide_total ++;
?>
<div class="cf slide icon-slide">
<?php
// up to 4 icons
if (is_array($icons) && !empty($icons[$k])) {
$icon1 = $icons[$k];
$k++;
}
?>
<div class="col left">
<div class="cf icon">
<div class="col thumb">
<img src="<?=$icon1['thumb']?>" alt="<?=htmlentities($icon1['post_title'])?>" />
</div>
<div class="colR details">
<h4><?=$icon1['post_title']?></h4>
<p><?=$icon1['post_content']?></p>
</div>
</div>
<?php
// up to 4 icons
if (is_array($icons) && !empty($icons[$k])) {
$icon2 = $icons[$k];
$k++;
}
?>
<div class="cf icon">
<div class="col thumb">
<img src="<?=$icon2['thumb']?>" alt="<?=htmlentities($icon2['post_title'])?>" />
</div>
<div class="colR details">
<h4><?=$icon2['post_title']?></h4>
<p><?=$icon2['post_content']?></p>
</div>
</div>
</div>
<?php
// up to 4 icons
if (is_array($icons) && !empty($icons[$k])) {
$icon3 = $icons[$k];
$k++;
}
?>
<div class="colR right">
<div class="cf icon">
<div class="col thumb">
<img src="<?=$icon3['thumb']?>" alt="<?=htmlentities($icon3['post_title'])?>" />
</div>
<div class="colR details">
<h4><?=$icon3['post_title']?></h4>
<p><?=$icon3['post_content']?></p>
</div>
</div>
<?php
// up to 4 icons
if (is_array($icons) && !empty($icons[$k])) {
$icon4 = $icons[$k];
$k++;
}
?>
<div class="cf icon">
<div class="col thumb">
<img src="<?=$icon4['thumb']?>" alt="<?=htmlentities($icon4['post_title'])?>" />
</div>
<div class="colR details">
<h4><?=$icon4['post_title']?></h4>
<p><?=$icon4['post_content']?></p>
</div>
</div>
</div>
</div> <!-- // end icon slide -->
<?php
} // end for $j (number of sets of 4 icons
?>
My proposed solution:
<?php if (!empty($icons)) {
$num_cols = 2;
$i = 0;
$slide_items = 4;
?>
<div class="cf slide icon-slide">
<?php foreach ( $icons as $icon ) {
echo $i++%$num_cols==0 ? '</div><div class="col" style="width: 250px;">' : '';
?>
<div class="cf icon">
<div class="col thumb">
<img src="<?=$icon['thumb']?>" alt="<?=htmlentities($icon['post_title'])?>" />
</div>
<div class="colR details">
<h4><?=$icon['post_title']?></h4>
<p><?=$icon['post_content']?></p>
</div>
</div>
<?php } } // end if we have icons attributes ?>
I'm having trouble figuring out how to make another slide after I hit 4 icons. Adding the following line before the end of the foreach loop hasn't worked.
echo $i++%$slide_items==0 ? '</div><div class="cf slide icon-slide">' : '';
Here's some logic for the loop:
$i = count( $icons );
if ( $i % 4 != 0 )
$i = $i + ( $i % 4 );
for( $n = 0; $n < $i; $n++ )
{
if ( $n % 4 == 0 )
{
// code to open a row here
}
// code to open a column here
// echo your icon here, use isset() or !empty().
// code to close a column here
if ( $n > 0 && $n % 3 == 0 )
{
// code to close a row here
}
}
The IFs at the top is for keeping the column number consistent. Otherwise there'll be some weirdness at the end of the loop.
Related
I have an ACF Repeater field i'd like to output as an accordion grid, like so:
<div class="intro row">
<div class="item item-1">name 1</div>
<div class="item item-2">name 2</div>
<div class="item item-3">name 3</div>
<div class="item item-4">name 4</div>
</div>
<div class="expanded row">
<div class="expand" id="item-1">expanded info 1</div>
<div class="expand" id="item-2">expanded info 2</div>
<div class="expand" id="item-3">expanded info 3</div>
<div class="expand" id="item-4">expanded info 4</div>
</div>
<div class="intro row">
<div class="item item-5">name 5</div>
<div class="item item-6">name 6</div>
<div class="item item-7">name 7</div>
<div class="item item-8">name 8</div>
</div>
<div class="expanded row">
<div class="expand" id="item-5">expanded info 5</div>
<div class="expand" id="item-6">expanded info 6</div>
<div class="expand" id="item-7">expanded info 7</div>
<div class="expand" id="item-8">expanded info 8</div>
</div>
I can group the initial row fine, it's just the second "expanded" row i'm having trouble with. How can I repeat and group the second row of 4 correctly in the same loop? My current PHP:
<?php // check if the repeater field has rows of data
if( have_rows('features') ):
// loop through the rows of data
// add a counter
$count = 0;
$group = 0;
while ( have_rows('features') ) : the_row();
$name = get_sub_field('feature_name');
$expandedInfo = get_sub_field('feature_info');
if ($count % 4 == 0) {
$group++;
?>
<div class="intro row">
<?php
}
?>
<div class="item item-<?php echo $count; ?>">
<?php echo $name ?>
</div><!-- item-->
<?php
if ($count % 4 == 3) {
?>
</div><!-- intro-->
<?php
}
$count++;
endwhile;
else :
// no rows found
endif;
?>
The second 'expanded' row can be done so that you store each count (item-1,item-2) in an array or just traverse through all the count when you close the intro row.
<?php
if ($count % 4 == 3) {
?>
</div><!-- intro-->
<div class="expanded row">
<?php
$start = $count-3;
// if $count is 4, $start will be 1, and the $i will go to 4
// if $count is 8, $start will be 5
for($i=$start;$i<=$count;$i++){
echo '<div class="expand" id="item-' . $i . '"></div>';
} ?>
</div>
<?php
}
This is just an example. I would suggest you to store each $count in an array and then use the count($array) to get the number of them. After you have traversed the array, reset it.
The Array Approach
<?php // check if the repeater field has rows of data
if( have_rows('features') ):
// loop through the rows of data
// add a counter
$count = 0;
$group = 0;
// Content Array
$content_array = array();
while ( have_rows('features') ) : the_row();
$name = get_sub_field('feature_name');
$expandedInfo = get_sub_field('feature_info');
// Adding the Expanded Info
$content_array[ 'item-' . $count ] = $expandedInfo;
if ($count % 4 == 0) {
$group++;
?>
<div class="intro row">
<?php
}
?>
<div class="item item-<?php echo $count; ?>">
<?php echo $name ?>
</div><!-- item-->
<?php
if ($count % 4 == 3) {
?>
</div><!-- intro-->
<div class="expanded row">
<?php
foreach( $content_array as $item_id => $expanded_info ) {
echo '<div class="expanded" id="' . $item_id . '">';
echo $expanded_info;
echo '</div>';
} ?>
</div>
<?php
// Resetting the Array
$content_array = array();
}
$count++;
endwhile;
else :
// no rows found
endif;
?>
okey, lets see ,
using variables to store your templates may helps a lot in this context ,
as follow :
$intro = '';
$expanded = '';
while (have_rows('features')) :
the_row();
if ($count % 4 == 0) {
$group++;
$intro .= '<div class="intro row">';
$expanded .= '<div class="expanded row">';
}
$intro .= '<div class="item item-' . $count . '"></div><!-- item-->';
$expanded .= '<div class="expand" id="item-' . $count . '"></div>';
if ($count % 4 == 3) {
$intro = '</div><!-- intro-->';
$expanded = '</div><!-- intro-->';
}
$count++;
endwhile;
I've made a quick example to explain to show you how using variables may fix your issue : https://3v4l.org/cKPP4
Can't test it right now, but I think something like that should work.
<?php // check if the repeater field has rows of data
if( have_rows('features') ):
// loop through the rows of data
// add a counter
$count = 0;
$group = 0;
$array = array();
while ( have_rows('features') ) : the_row();
$name = get_sub_field('feature_name');
$expandedInfo = get_sub_field('feature_info');
if ($count % 4 == 0) {
$group++;
?>
<div class="intro row">
<?php
}
?>
<div class="item item-<?php echo $count; ?>">
<?php echo $name ?>
</div><!-- item-->
<?php
array_push($array, $expandedInfo);
if ($count % 4 == 3) {
?>
</div><!-- intro-->
<div class="expanded row">
<?php
for ($i=0; $i < count($array); $i++) {
echo '<div class="expand" id="item-'.$i + 1.'">'.$array[$i].'</div>';
}
echo '</div>';
}
$count++;
endwhile;
else :
// no rows found
endif;
?>
So I'm working on a HTML carousel using Twitter Bootstrap, Wordpress and ACF Fields.
This carousel shows 2 items per row. Each of these items has a class of "col-md-6". So by showing 2 items per row, the total is 2 columns of "col-md-6" (which is perfect since this completes the 12 columns required by Bootstrap):
Here is my code:
<?php if (have_rows('columns_carousel_slide')) {
$count = 0; ?>
<div class="item active"><div class="row">
<?php while(have_rows('columns_carousel_slide')) {
the_row();
if ($count > 0 && (($count % 2) == 0)) {
?>
</div> <!--.item -->
</div> <!--.row -->
<div class="item">
<div class="row">
<?php } ?>
<div class="col-md-6">
<h2><?php the_sub_field('columns_carousel_slide_title'); ?></h2>
</div> <!--.col-md-6 -->
<?php $count++; } ?>
</div> <!--.item -->
</div> <!--.row -->
<?php } ?>
However, I would like to know if there's a way to detect if there's 1 item per row and if so, then show a "col-md-12" instead of a "col-md-6" in order to fill in the remaining space of not having 2 items.
Any ideas are welcome.
Thanks!
--
Edit: As suggested by Jakub, I've updated my code to the following:
<?php if (have_rows('columns_carousel_slide')) {
$count = 0; ?>
<div class="item active"><div class="row">
<?php
$multiplier = 1; //that could actually go before the while
if (count(get_field('columns_carousel_slide'))%2 === 1 &&
$count === count(get_field('columns_carousel_slide'))-1) {
$multiplier = 2;
} ?>
<?php while(have_rows('columns_carousel_slide')) {
the_row();
if ($count > 0 && (($count % 2) == 0)) {
?>
</div> <!--.item -->
</div> <!--.row -->
<div class="item">
<div class="row">
<?php } ?>
<div class="col-md-<?php echo (6*$multiplier);?>">
<h2><?php the_sub_field('columns_carousel_slide_title'); ?></h2>
</div> <!--.col-md-6 -->
<?php $count++; } ?>
</div> <!--.item -->
</div> <!--.row -->
<?php } ?>
However, I think I've must have missed something because I am getting total of "col-md-12" for all the rows.
Assuming that "get_field" returns the array with all rows, then you would need to change the following:
<div class="col-md-6">
<h2><?php the_sub_field('columns_carousel_slide_title'); ?></h2>
</div> <!--.col-md-6 -->
with this:
<?php
$multiplier = 1; //that could actually go before the while
if (count(get_field('columns_carousel_slide'))%2 === 1 &&
$count === count(get_field('columns_carousel_slide'))-1) {
$multiplier = 2;
} ?>
<div class="col-md-<?php echo (6*$multiplier);?>">
<h2><?php the_sub_field('columns_carousel_slide_title'); ?></h2>
</div> <!--.col-md-12 -->
A short explanation:
initially we set the multiplier to 1 (so that 6*1 = 6 for paired
columns).
we do a condition to check if number of items is even
and we are currently processing the last item. If so - we set the
multiplier to 2 (so that 6*2 = 12 for single column)
we set the class to be "col-md-" and the result of our calculation (either 6 or 12)
I've made a logo slider using Bootstrap (basically as seen here http://jsfiddle.net/juddlyon/Q2TYv/10/).
Within each slide there are 4 logos. I want to make this responsive, where on smaller screens it only shows 2 logos per slide. I'm not sure what the best way is to do this.
I can double the grid-4 width to 50% with media queries but then it will still show 4 per slide, in a 2x2 grid.
Another way is to duplicate the entire slide and hide and show the correct one, but this seems like a rather inefficient appreach.
So really I need to reduce the number of logos per slide as it is loaded.. but how?
I'm using WP and Advanced Custom Fields to populate the slider. Simplified code below:
PHP:
<?php
$firstslide = 0;
$slide = 0;
$repeater = get_field('clients', $clients);
$order = array();
foreach( $repeater as $i => $row ) {
$order[ $i ] = $row['name'];
}
array_multisort($order, SORT_ASC, $repeater);
if($repeater):
foreach($repeater as $i => $row):
if ($firstslide == 0) {
$class = "item active";
} else {
$class = "item";
};
if ($slide == 0) {
echo '<div class="' . $class . '">';
};
?>
<div class="grid-4">
<img src="<?php echo $row['logo']; ?>">
</div>
<?php
if ($slide == 4) {
echo '</div>';
$slide = 0;
} else {
$slide++;
}
$firstslide++;
endforeach;
wp_reset_postdata();
endif;
?>
This would results in something like:
<div class="item active">
<div class="grid-4"><img src="logo1.jpg"></div>
<div class="grid-4"><img src="logo2.jpg"></div>
<div class="grid-4"><img src="logo3.jpg"></div>
<div class="grid-4"><img src="logo4.jpg"></div>
</div>
<div class="item">
<div class="grid-4"><img src="logo5.jpg"></div>
<div class="grid-4"><img src="logo6.jpg"></div>
<div class="grid-4"><img src="logo7.jpg"></div>
<div class="grid-4"><img src="logo8.jpg"></div>
</div>
<div class="item">
<div class="grid-4"><img src="logo9.jpg"></div>
<div class="grid-4"><img src="logo10.jpg"></div>
<div class="grid-4"><img src="logo11.jpg"></div>
<div class="grid-4"><img src="logo12.jpg"></div>
</div>
Very simplified CSS for the grid:
.grid-4 {
width: 25%;
}
After more searching, it looks like Slick is a solution that will just take care this.
jsfiddle.net/BishopBarber/ufnjkjy4/1/
I'm currently wrapping every two divs in a parent row with php, which is working great.
However what I need to do is have it so that the 3rd & 4th, 7th & 8th etc divs have a different layout. This is currently my code to wrap every two divs in a parent row.
<?php
if( have_rows('products') ) :
$counter = 1;
$i = 0;
?>
<div class="o-table l-grid-half">
<?php while( have_rows('products') ) :
the_row();
if ($i > 0 && ($i % 2 == 0)) {
// close row and open new row
?>
</div>
<div class="o-table l-grid-half">
<?php } ?>
<div class="o-table-cell l-grid-half__item ">
<div class="o-table-cell l-grid-half__item ">
<img src="<?php the_sub_field('product_image'); ?>"/>
</div>
<div class="o-table-cell o-table-vt l-grid-half__item o-full-sm-pd o-roman l-product__item o-bg-item-<?php echo($counter);?>">
<h3 class="hd-panel-sm"><?php the_sub_field('product_heading'); ?></h3>
<?php the_sub_field('product_summary'); ?>
<i class="icon-right-open"></i><span>Find out more</span>
</div>
</div>
<?php
$i++;
$counter++;
endwhile;
?>
</div>
<?php endif;
?>
Everything I have tried to wrap it into the existing code has broken the script.
The end goal I would like the html to look like this (simplified version):
<div class="o-table im-the-parent-row">
<div class="o-table-cell im-the-child-div">
<img src="img-on-the-left.jpg"/>
<p>text on the right</p>
</div>
<div class="o-table-cell im-the-child-div">
<img src="img-on-the-left.jpg"/>
<p>text on the right</p>
</div>
</div>
<div class="o-table im-the-parent-row">
<div class="o-table-cell im-the-child-div">
<p>text on the left</p>
<img src="img-on-the-right.jpg"/>
</div>
<div class="o-table-cell im-the-child-div">
<p>text on the left</p>
<img src="img-on-the-right.jpg"/>
</div>
</div>
Updated code:
<?php
if( have_rows('products') ) :
$counter = 1;
$i = 0;
?>
<div class="o-table l-grid-half">
<?php while( have_rows('products') ) :
the_row();
if ($i > 0 && ($i % 2 == 0)) {
// close row and open new row
?>
</div>
<div class="o-table l-grid-half">
<?php } ?>
<!--Row 3&4, 7&8 have the image on the left -->
<?php if($i > 0 && (($i % 4 == 0) || (($i+1) % 4 == 0))) { ?>
<div class="o-table-cell l-grid-half__item ">
<div class="o-table-cell o-table-vt l-grid-half__item o-full-sm-pd o-roman l-product__item o-bg-item-<?php echo($counter);?>">
<h3 class="hd-std-sm"><?php the_sub_field('product_heading'); ?></h3>
<?php the_sub_field('product_summary'); ?>
<i class="icon-right-open"></i><span>Find out more</span>
</div>
<div class="o-table-cell l-grid-half__item ">
<img src="<?php the_sub_field('product_image'); ?>"/>
</div>
</div>
<?php } else {?>
<!--Row 1&2, 5&6 have the image on the right -->
<div class="o-table-cell l-grid-half__item ">
<div class="o-table-cell l-grid-half__item ">
<img src="<?php the_sub_field('product_image'); ?>"/>
</div>
<div class="o-table-cell o-table-vt l-grid-half__item o-full-sm-pd o-roman l-product__item o-bg-item-<?php echo($counter);?>">
<h3 class="hd-std-sm"><?php the_sub_field('product_heading'); ?></h3>
<?php the_sub_field('product_summary'); ?>
<i class="icon-right-open"></i><span>Find out more</span>
</div>
</div>
<?php } ?>
<?php
$i++;
$counter++;
endwhile;?>
</div>
<?php endif;
?>
This code gives you a "true" when $i is multiple of 4:
($i > 0 && ($i % 4 == 0)) # -> 4rd, 8th, etc
You can then shift $i to get the 3rd and 7th itens:
($i > 0 && ($i+1) % 4 == 0) # -> 3rd, 7th, etc
EDIT - To get both cases at once:
if($i > 0 && (($i % 4 == 0) || (($i+1) % 4 == 0))) {
/* do something... when $i = 3,4,7,8,11,12,... */
}
Take one variable starts with 1
Increment with every loop... 1 2 3 4
After 4 move back to 1
When its 3 and 4 you can write your custom code.
(You can save as variable or in session as you wish)
I'm using a foreach loop to output images fetched from the Instagram API.
I want to split the outputted images in groups of four and five and in addition to that add a div element to each group except the last one where 2 div's should be added, so I get the following structure:
<div class="group>
<div class="extra"> </div>
<img/>
<img/>
<img/>
<img/>
</div> <!-- Close group of 5 -->
<div class="group>
<div class="extra"> </div>
<img/>
<img/>
<img/>
<img/>
<img/>
</div> <!-- Close group of 6 -->
<div class="group>
<div class="extra"> </div>
<img/>
<img/>
<img/>
<div class="extra"> </div>
</div> <!-- Close group of 5 -->
By using modulus in the loop I've manage to group the elements with the correct number of items in each group, but when I try to add the extra div to each group it breaks the counting and I'm no longer getting the correct number of elements grouped together. The code I'm currently using to print out the images (12 in total):
<div class="group"> <!-- Open group-wrapper -->
$count = 0;
foreach($decoded_results['data'] as $item) {
if ($count % 11 == 0 || $count % 11 == 5 ) {
echo '<div class="extra"> </div>';
echo '</div> <div class="group">';
}
echo '<a target="_blank" href=' .$link_url. '>';
echo '<div class="img-wrapper">';
echo '<img src="'.$image_link.'" /> </div> </a>';
$count++;
}
Any suggestion how this can be achieved?
This will be enough to point you in the correct direction:
<div class='group'>
<div class='extra'></div>
<?php
$i = 1;
$j = 1;
$step = 4;
$count = count($decoded_results['data']);
foreach($decoded_results['data'] as $k => $v) {
?>
<a target='_blank' href='<?php echo $v;?>'>
<div class='img-wrapper'>
<img src='<?php echo $v;?>' />
</div>
</a>
<?php
if (($j % $step) == 0 && $i < $count) {
?>
</div>
<div class='group'>
<div class="extra"></div>
<?php
$step = ($step == 4) ? 5: 4;
$j = 0;
}
$j++;
$i++;
}
?>
<div class='extra'></div>
</div>
On a side note you should be aware that having a div (block element) inside an a (inline element) isn't exactly semantic HTML, but still widely accepted nowadays. I personally tend to avoid this and can do by using CSS.
If you're using PHP use the array_chunk() function
http://php.net/manual/en/function.array-chunk.php