I want to display all my categories in one page, 4 items per row.
If I have 4,8 or 12 items then I have no problem, however if I have 5 items or any "number of items" that is not divisible by 4 without any remainder appears on the next row (as I have set each item 25% of the screen with css) with subsequent gap space which looks really odd and empty. This is a problem and I call those remainder items indeBox as in independent boxes.
My end goal is to align those independent boxes on the centre.
I am trying to create an algorithm for this purpose.
Here is what I have done so far
The following function takes two parameters.
numberRestriction is the number of items allowed per row (4)
childrens is an object with all categories.
I am counting how many categories are present within the childrens object
and finding out if there are remainders.
function calculateDivision($numberRestriction, $childrens)
{
$arrayobj = new ArrayObject($childrens);
$itemLenght = $arrayobj->count();
$itemBasket = $itemLenght;
$remaining = $itemBasket % $numberRestriction;
return $remaining;
}
On the template
<?php
//$term = get_queried_object();
$childrens = get_categories(array('parent' => 27,'hide_empty' => false));
$rowRestriction =4;
$indeBox = calculateDivision($rowRestriction, $childrens);
$arrayobj = new ArrayObject($childrens);
$itemLenght = $arrayobj->count();
$i = 0;
if($indeBox == 0)
{
foreach($childrens as $index => $children)
{
$cat_image = z_taxonomy_image_url($children->term_id);
$cat_id = $children->term_id;
$desc = #explode('|', $term->description);
?>
<a href="<?php echo get_category_link($cat_id) ?>" >
<div class="food_list_single menus_list" style="background: url(<?php echo $cat_image ?>) no-repeat scroll right center / cover ">
<div class="food_hover menus_hover ">
<p style="width: 100%; overflow: hidden; padding: 10px; text-align: center;" class="food_hover_title_small"><?php echo $desc[2] ?></p>
<p class="food_hover_title"><?php echo $children->name ?></p>
<button class="btn btn-default food_button"><i class="fa fa-eye"></i>View Details</button>
</div>
</div>
</a>
<?php
} //foreach ends
}else
{
//loop all items
//set a counter
//everytime the counter reaches maximum item allowed in a row, counter should reset and add class to row even
//once it finds odd number in a row it should call the row uneven
$counter1 = 0;
foreach($childrens as $index => $children)
{
$counter1++;
$cat_image = z_taxonomy_image_url($children->term_id);
$cat_id = $children->term_id;
$desc = #explode('|', $term->description);
//out put div
?>
<a href="<?php echo get_category_link($cat_id) ?>" >
<div class="food_list_single menus_list" style="background: url(<?php echo $cat_image ?>) no-repeat scroll right center / cover ">
<div class="food_hover menus_hover ">
<p style="width: 100%; overflow: hidden; padding: 10px; text-align: center;" class="food_hover_title_small"><?php echo $desc[2] ?></p>
<p class="food_hover_title"><?php echo $children->name ?></p>
<button class="btn btn-default food_button"><i class="fa fa-eye"></i>View Details</button>
</div>
</div>
</a>
<?php
//also track the last items index
$last_items_index = $index;
?>
<?php
}
echo "Inde items :".$indeBox; //finds how many indeboxes
echo " Last items index " . $last_items_index ;
}
?>
Image
Solution: Not beautiful or efficient, but it works
Find out how many items in the array attach to a variable.
Find out how many boxes fit in a row and attach to a variable.
Calculate independent boxes using following function:
.
function calculateDivision($numberRestriction, $childrens)
{
$arrayobj = new ArrayObject($childrens);
$itemLenght = $arrayobj->count();
$itemBasket = $itemLenght;
$remaining = $itemBasket % $numberRestriction;
return $remaining;
}
Since I already know 4 boxes fit in a row, so there can only be either 1,2 or 3 independent boxes. and if there are 4 boxes then there are no independent boxes. I can run conditions
if($indeBox == 1)
{
//if there are one independent box remaining
//find the last item of the array and put a bootstrap class col-md-offset-3 to
//if not last item, no need for adding additional class
}
else if($indeBox == 2)
{
//if there are two independent boxes remaining
//find the second last item of the array and put a bootstrap class col-md-offset-3 to
//if not last item, no need for adding additional class
}
else if($indeBox == 3)
{
//if there are three independent box remaining
//find the third last item of the array and put a bootstrap class col-md-offset-3 to
//if not last item, no need for adding additional class
}
Related
I want to display a product page with every item aligned with each other. These products are dynamically generated using PHP code. The problem is, they won't align horizontally when one product has a longer name than the other.
To further understand my problem, here is a screenshot:
You can see that the product prices are not aligned with each other because they are influenced by the length of the product names.
Here is my PHP and HTML code:
<!--PHP CODE FOR EXTRACTING DATA FROM TABLE-->
<div class="span_container">
<div class="col-md-4 bottom-cd simpleCart_shelfItem" style="display: inline-block;">
<div class="product-at ">
<a href="single.php"><img class="img-responsive" style="width:300px; height:auto;" src="/EDGE/storeadmin/product_images/<?php echo $row['i_image']; ?>" alt="">
<div class="pro-grid">
<span class="buy-in">View Details</span>
</div>
</a>
</div>
<p class="tun"><?php echo $row['i_name'];?></p>
<p class="number item_price"><i> </i>₱<?php echo $row['i_price']; ?></p>
</div>
</div>
And this is the CSS code of my paragraph (tun):
p.tun {
font-size:1em;
color: #949494;
text-align: center;
line-height: 1.3em;
padding: 1em 0;
}
This is simple. Set position:relative; for the containing .simpleCart class, and a height like height:300px - replace 300 with whatever your box height needs to be so every containing box has the same height.
Then use position:absolute; to position the elements within .simpleCart according to the heights that we know already.
We know and can deduce:
the height of the image: therefore we use, as an example: position:absolute;top:5%; - change 5% according to your needs.
the height of the product prices and that those will be at the bottom no matter how high the .simpleCart box will be. So we use position:absolute;bottom:5% - change 5% according to your needs, again. Now every product price is at the same level. Provided that every .simpleCart box is of the same height.
Finally, we place the paragraph text with the .tun class in between with position:absolute;top:150px; - where you change 150 according to your needs so it fits between the image and the product pricing.
You can use the following js function to match the module heights to the tallest.
equalheight = function(container){
var currentTallest = 0,
currentRowStart = 0,
rowDivs = new Array(),
$el,
topPosition = 0;
$(container).each(function() {
$el = $(this);
$($el).height('auto')
topPostion = $el.position().top;
if (currentRowStart != topPostion) {
for (currentDiv = 0 ; currentDiv < rowDivs.length ; currentDiv++) {
rowDivs[currentDiv].height(currentTallest);
}
rowDivs.length = 0; // empty the array
currentRowStart = topPostion;
currentTallest = $el.height();
rowDivs.push($el);
} else {
rowDivs.push($el);
currentTallest = (currentTallest < $el.height()) ? ($el.height()) : (currentTallest);
}
for (currentDiv = 0 ; currentDiv < rowDivs.length ; currentDiv++) {
rowDivs[currentDiv].height(currentTallest);
}
});
}
$(window).load(function() {
equalheight('.equalise-height');
});
This question already has answers here:
PHP How to determine the first and last iteration in a foreach loop?
(21 answers)
Closed 7 years ago.
Using codeigniter framework i have this code here
<?php
foreach ($allposts as $posts) {
echo '<div class="col-sm-1">
<div class="thumbnail">
<img class="img-responsive user-photo" src="https://ssl.gstatic.com/accounts/ui/avatar_2x.png">
</div><!-- /thumbnail -->
</div><!-- /col-sm-1 -->
<div class="col-sm-11">
<div class="panel panel-default companel">
<div class="panel-heading companel-heading">
<strong>'.$posts->author_name.'</strong> <span class="text-muted">'.unix_to_human($posts->post_date).'</span>
</div>
<div class="panel-body">
'.$posts->post.'
</div><!-- /panel-body -->
</div><!-- /panel panel-default -->
</div><!-- /col-sm-11 -->';
}
?>
now i want to except first result or first post in my case ? it is possible
and another question may i do something like display posts but one by one i mean align one right and second one left?
You can initialize a variable outside the foreach and count inside the iteration.
$count=0;
foreach($allposts as $posts)
{
$count++; // incrememnt
if($count==1)
{
// this is the first post
}
}
Option 2:
Use for loop instead of foreach
for($i=0; $i<=count($allposts); $i++)
{
if($i==0) // this is the first post.
echo $allposts[$i];
}
Using CSS to float your posts:
.post:nth-child(odd){
float: left;
}
.post:nth-child(even){
float: right;
}
You can declare a var $count outside the foreach loop, initilize it to 0 and increment it at the end of the loop. At the beginning of the loop check if the $count variable is 0 - if that is the case - skip the echo.
To display one row aligned to the left and one to the right check the same $count variable: if $count%2 == 0 then align one direction else the other.
foreach($value as $k => $v)
{
if($k === 0)
{
continue;
}
// rest your case
}
every second item needs to be on right side of the page, but inline with first item, so it would create 2x2 type grid of both echoed items.
I added some CSS like this
.container{float:left; width:50%;} but it didn't work.
if ($file6 % 2 == 1)
{
echo '<div id="container">
<div id="thumbnail">
<img src="/images/tirgus/thumbs/'.$row['id'].'.jpeg" width="141" height="74" alt="image" />
</div>
<br>
<div id="info1"><sub>' .cleanString($file2).'</sub></div>
<br>
<div id="info2"><sub>Telefons: ' .cleanString($file3). '</sub><br><sub>email: '.cleanString($file4).'</sub></div><br>
<div id="info3"><sub>Iepostoja:</sub> ' .cleanString($file5). '</div><br>
</div><widgets><customization><css> <link rel="stylesheet" href="template_faili/gallery.css"></css></customization></widgets>';
}
else if ($file6 % 2 == 0) {
echo '<div id="container2">
<div id="thumbnail2">
<img src="/images/tirgus/thumbs/'.$row['id'].'.jpeg" width="141" height="74" alt="image" />
</div>
<br>
<div id="info1"><sub>' .cleanString($file2).'</sub></div>
<br>
<div id="info2"><sub>Telefons: ' .cleanString($file3). '</sub><br><sub>email: '.cleanString($file4).'</sub></div><br>
<div id="info3"><sub>Iepostoja:</sub> ' .cleanString($file5). '</div><br>
</div><widgets><customization><css> <link rel="stylesheet" href="template_faili/gallery.css"></css></customization></widgets>';
}
}
.container{float:left; width:50%;}
will be want you want. FYI, please DO NOT use duplicate ids in your html.
In the interest of showing how you would use a modulo to achieve this, you would want to do something like:
foreach($files as $file_count => $file) {
if ($file_count % 2 == 0)
{
echo '<div class="thumb row">';
}
echo '
<div class="container">
<div class="thumbnail">
<a href="/images/'. $file .'" title="'.cleanString($file).'" class="thickbox">
<img src="/images/'.$row['id'].'.jpeg" width="141" height="74" alt="image" />
</a>
</div>
<br />
<div id="info"><sub>' .cleanString($file2).'</sub></div>
<br />
<div id="info"><sub>text ' .cleanString($file3). '</sub><br><sub>email: '.cleanString($file4).'</sub></div>
<br />
<div id="info"><sub>text </sub> ' .cleanString($file5). '</div>
<br />
</div>';
if ($file_count % 2 == 1)
{
echo '</div>';
}
}
Note that the above will probably not work as-is with your script because I am using a made up array that loops with the value $file while your code appears to have the various values in separate arrays. The overall idea is this:
foreach($files as $file_count => $file) {
Loops over each image/file you are wanting to output, starting at 0, so that :
$file_count % 2 == 0
indicates the first of two pair and
$file_count % 2 == 1
indicates the second of two pair.
So before the first of two are output, you start a container div such as:
<div class="thumb row">
Then you output your interior html as you already are, using the same html for both thumbnails.
and after the second of two are output, you close that div via:
</div>
Now each two of your thumbnail divs are wrapped in the thumb row container div, allowing you to apply css such as:
.thumb.row .container {
display: inline-block;
}
which will line them up side by side but still break on the outer row div.
Also, in addition to this being an ill-advised approach, you should not be setting the id attribute inside a loop, as this will set the same id to multiple elements, which is invalid HTML. Instead, update the code to use class which can be applied to multiple elements.
Each div need to use different classes/ids, where the inline behavior is defined or not.
$col[0] = 'class1';
$col[1] = 'class2';
for ($i=0; $i<$count; $i++) {
$output .= '<div class="'. $col[$i%2] . ' >';
}
I created a page to display messages that are saved into a database.The messages are displayed with a picture. I have the following DIV layout:
<div id="MessageWrapper">
<div id="MessagePicture"></div>
<div id="MessageText">
<div id="MessageTitle"></div>
<div id="MessageContent"></div>
</div>
</div>
I wanted the div 'MessagePicture' and 'MessageText' to alternate their position (left and right) So The final code I have is:
$i = 0;
while ($Row = mysql_fetch_assoc($Result))
{
$class = (++$i % 2) ? 'even' : 'odd';
echo '
<div id="MessageWrapper">
<div id="MessagePicture" class="'.$class.'">
<style>
#MessagePicture {
background-image: url(../../../Images/'.stripslashes($Row['Code']).'.png);
background-repeat: no-repeat;
background-position: center
</style>
</div>
<div id="MessageText" class="'.$class.'">
<div id="MessageTitle">
<h1>'.$Row['NameBox'].'</h1>
</div>
<div id="MessageContent">
<p>'.nl2br($Row['MessageBox']).'</p>
</div>
</div>
</div>
The problem I'm facing: although the parsed source code has different codes ($Row['Code']) in the url of the background image, all the messages display the same image.
It is always the first image of the first ($Row['Code']) that is entered into the database.
Does anyone know how to resolve this problem?
Give each of your divs a unique id. For example:
$i = 0;
while ($Row = mysql_fetch_assoc($Result))
{
$class = (++$i % 2) ? 'even' : 'odd';
echo '
<div id="MessageWrapper'.$i.'">
<div id="MessagePicture'.$i.'" class="'.$class.'">
<style>
#MessagePicture'.$i.' {
background-image: url(../../../Images/'.stripslashes($Row['Code']).'.png);
}
</style>
... etc ...
}
You end up with the first div having an id of MessagePicture1 and a corresponding #MessagePicture1 style, the next one MessagePicture2, and so on.
I have this loop which basically displays a block on the page with an image in it, the class gallerypic has a margin of 20px on the right, it also has the rule float:left;, the issue is every time the third div is created it starts on a new line, because the margin is pushing it there. So Ideally every third post I would like no margin, and to apply a div gallerypicright or something.
Im wondering does someone have a solution to this? Possibly an easier one that simply stops the margin from happening when its the third one? I need the margin on the other two as it creates a neat gap between the posts.
<?php
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$archive_query = new WP_Query('cat=14&showposts=14&paged=' . $paged);
$id = get_the_ID();
while ($archive_query->have_posts()) : $archive_query->the_post(); ?>
<div class="events">
<div class="gallerypic"><div class="limerickguideblockheader"><p><a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>"><?php the_title(); ?>
</div>
<div class="gallerypiccontainer"><a href="<?php the_permalink(); ?>" >
<?php echo get_the_post_thumbnail( $id, 'gallery-thumb', $attr ); ?> </a></div>
</div>
</div>
<?php endwhile; ?>
edit: a picture paints a 1000 words, here is the link so far, with three posts...
http://limerickfc.hailstormcommerce.com/cms/?page_id=2466
A method via CSS would be even better if possible.
Cheers
Adrian
Try the below code.
<style>
.gallerypicright {
margin: 0;
}
</style>
...
<?php
$count = 0;
while ($archive_query->have_posts()) : $archive_query->the_post();
$count++;
$third_div = ($count%3 == 0) ? 'gallerypicright' : '';
?>
...
<div class="gallerypic <?php echo $third_div; ?>">
If you want a pure CSS solution, you could try using
.gallerypic:nth-child(3n + 1) {
margin:0;
}
n is a counter that goes up for every element. The counter (n) starts at 0 but the elements on the page start at 1, so the 3n + 1 means for every 3 * n + 1 elements, e.g.:
element 1 (3 * 0 + 1), 4 (3 * 1 + 1), 7 (3 * 2 + 1) etc.
This solution is only available in CSS3, so older browsers won't have it. (see: http://caniuse.com/#search=nth-child).
Note that :nth-child counts all children, so you should group the events in a div:
<div class="container">
<div class="gallerypic">...</div>
<div class="gallerypic">...</div>
<div class="gallerypic">...</div>
</div>
you have to count your post after that in loop you have to module by 3 to total no of post & apply the right class in given post such as
if ($cnt%3 == 0){ $class = 'right'}
You might try the trick of adding a balancing negative right margin on your container, so in your case, perhaps
div.events { margin-right: -20px; }
Or, if you can cope with the slightly patchy browser support (IE9+ only, better in other browsers, I think) perhaps style using nth-child:
.gallerypic:nth-child(3n+3) { margin-right: 0px; }