Add custom classes in function of index in "collection" of blocks

Permalink 1 user found helpful
Hi!

I started developing in Concrete5 today and I was thinking how it was possible to add a custom class to a block in function of the index in the "list of blocks".

It will be easier to understand with an example:
I have this area:
<?php
$a = new Area('Home_skills');
$a->display($c);
?>

This area contains custom blocks (of the same type).
The block view is:
<div class="block">
<span class="block_title">
...

I would like to give the third block of this "area" a custom class "last" :
<div class="block last">...

It works fine when I check it with a custom ID like this:
<div class="block <?php if($this->getBlockObject()->getBlockID() == 84): echo " last"; endif;?>

But that's definitely not a good solution...
Is there a way to achieve this? A solution could be to loop the block in an array but I dont know how this is possible:
Example
$a = new Area('Home_skills');
$index = 0;
foreach($a->getBlock() ...){
if(index%3){echo "last"};
$index++;

Thanks!

 
JohntheFish replied on at Permalink Reply
JohntheFish
Do you need the class, or is the class just a method of selecting it later?

For example, you could specify css with the :first-child or :last-child selectors:

http://www.quirksmode.org/css/firstchild.html...

Or you could select similarly using jQuery (including nth child).

http://api.jquery.com/nth-child-selector/...
benske replied on at Permalink Reply
Thanks for your answer John!

Yes, I know that you can do it in CSS via last-child, but this selector is not known in IE7 :( en jQuery can only change this after DOM is loaded so it is not so fast. Therefore I want to put it directly with PHP. I need this also for "odd" en "even" CSS classes (what is also possible via CSS know but not cross-browser too (CSS3).
JohntheFish replied on at Permalink Best Answer Reply
JohntheFish
You could achieve it by changing the part of the theme that outputs an area to get a list of blocks and output then 1 at a time. Then set a block wrapper for each block (some themes already do this). Within the block wrapper set a class that has an incrementing suffix.

If you want to get advanced, you could do similar by over-riding the core area class and leaving the theme alone.

Or you could create an alternate view template for the block in question to do similar just for the one block type, incrementing a global and using it as a suffix for your wrapping class.

In the PRB at the moment is a wrapper block that you can put before and after other blocks to open and close a div (you could do the same with an html block, but it would give issues in edit mode).

I do similar in Magic Tabs & Magic Toggle, using marker blocks as a point to create wrappers, but that uses JavaScript.
benske replied on at Permalink Reply
Thanks for your great and helpful answer JohntheFish!

This did the trick:
$a = new Area('Home_timeline_events');
foreach ($a->getAreaBlocksArray($c) as $key => $block) {
    ?>
    <div class="life_event<?php if($key&1): echo " odd"; endif; ?>"> 
    <?php 
        $block->display();
    ?>
    </div>
    <?php
}


Hope it isn't bad code :-)

I also found a method "
$blocks = $c->getBlocks('Home_timeline_events');
", is this a better way for having the block for an area?
JohntheFish replied on at Permalink Reply
JohntheFish
What you have done is probably the simplest and as you have a solution that works for you, you should stick with it.

If it were an addon/theme going through the prb, there may be some finer points of using built in methods of an area object. I would have to look at the c5 area object in detail to get that picky.
jordanlev replied on at Permalink Reply
jordanlev
I have this problem all the time. If you're running 5.6 or higher, I have a very elegant solution (IMHO):
https://github.com/jordanlev/c5_block_wrapper_templates...

Let me know if you need any help getting that set up.

-Jordan
benske replied on at Permalink Reply
Thanks for sharing Jordan, this is great! Was exactly what I needed.

May I use it in my themes?