Add a Class to container element in first block in Area
Permalink 1 user found helpful> Heading
> Description
> "Read More" link
This is an HTML5 site I'm building and each block is wrapped in a <section> element generated in the view.php file for the custom block. All well so far....
However, on one page type these blocks go on, I need to add a class of "first" to the first <section>, which equates to the first Block rendered within the area.
How do I ascertain the first block rendered in an area and modify its HTML to add 'class="first"' to the section tag?
This may be a dumb question, but this is my first build using C5...

If I can do this, then I can put a simple conditional line in the view.php code that adds the HTML around the fields to allow me to put in class="first" or similar for the first block.
I see from core concrete code that the Area code for display($c) loops through all of the blocks for the Area, but I don't want to be doing anything in there, so hoping I can intercept it at the view.php to add my extras.
Thanks.
Now, option two. You can set the area to recognize which page id it is in like so (x=your page ID):
<section class="<?php if ($c->getCollectionID() == x){ echo 'last'; } ?>"> <p>content</p> </section>
Option three, you simply tell concrete5 to get the page handle and add it as a class.
Then you can style that section per page in your css:
<section class="<?php echo $c->getCollectionHandle(); ?>"> <p>content</p> </section>
Option four, you can determine all of these things at once, plus only do it if there is a block there:
$pageHandle = $c->getCollectionHandle(); $pageID = $c->getCollectionID(); $a = new Area('Header'); $a->display($c); if (!$a->getTotalBlocksInArea($c) > 0) { echo '<section class="' . $pageID . ' ' . $pageHandle . '">'; }
I hope I could help! :-D
EDIT: You can also do this:
$inlineJS = '<script type="text/javascript">$(document).ready(function() {$("#sectionParent section:first-child").addClass("last");});</script>'; $pageID = $c->getCollectionID(); if ($pageID == x) { echo $inlineJS; } else { //do something else here if page ID isn't right. }
$last = if ($c->getCollectionAttributeValue('last')){ echo 'class="last"'; } <section <?php $last ?>> <p>content</p> </section>
That way you can create the page attributes in the backend, and then for the page you want to echo the class="last" bit, you simply add the attribute to that particular page.
:-D
Each of my blocks contains a Heading, Description, Link.
In the view.php I have:
$linkedPage = $this->controller->getLinkedPage(); $nh = Loader::helper('navigation'); if ($linkedPage) { $pageURL = $nh->getLinkToCollection($linkedPage); $content = "{$detail} <a href=\"{$pageURL}\" class=\"more\">More »</a>"; } else { $content = $detail; } echo "<section>\n"; echo "<h3>{$heading}</h3>\n"; echo "<p>{$content}</p>\n"; echo "</section>\n";
So each block comes out as a fully formed section set.
When my page renders them, I just want to add class="first" to the first block.
I don't want to add it to the view (as what if these blocks are pulled for display elsewhere), I want to add it only on a particular template where the HTML is specific.
I don't want the user going in and setting attributes on what should be determinable from the system, and also, what if they change the sort order of the blocks? They would have to remember to remove and re-set attributes. Likewise, having users edit CSS is not desirable in this instance.
Thanks for the detail, but I'm not sure it solves my problem...but I might be wrong!
If there is a section element underneath the parent element on a certain page id, this will add the class to the first section element it encounters. That means you don't have to worry about whether they are putting other blocks in front of your section block, or whether they change the blocks ordering.
The main problem is determining what page to do this on, and I selected the page id to check (if you know this ahead of time). But you can use a page attribute check to determine what page to activate the code snippet on. The above still applies: it won't matter whether they reorder blocks, or put different blocks everywhere. This will only select the first occurring section element inside the specified parent on the specified page ID.
//put this code into header $inlineJS = '<script type="text/javascript">$(document).ready(function() {$("#sectionParent section:first-child").addClass("first");});</script>'; $pageID = $c->getCollectionID(); if ($pageID == x) { echo $inlineJS; }
I'm guessing I can't work out the 1st, 2nd, 3rd, nth block in an area as it's prepared for rendering unless wanting to mess about with core Concrete?
http://www.concrete5.org/community/forums/customizing_c5/find-the-l...
Maybe one of their solutions will give you an idea?
In your header.php, include phpQuery file (see below for website) like so:
include('phpQuery-onefile.php');
In your editable area where you are going to place your section blocks, place this code:
//x == your page ID you want this to work on if ($c->getCollectionID() == x) { ob_start(); $a = new Area('Header'); $a->display($c); $get = ob_get_clean(); $doc = phpQuery::newDocumentHTML($get); $doc['section']->filter(':first')->addClass('first'); echo phpQuery::getDocument($doc->getDocumentID()); } else { $a = new Area('Header'); $a->display($c); }
I have tested it, and it works to add the class .first to the first <section> tag it encounters for the page ID you want it to work on in the editable area you specify (Header, in this case). Again, you could use the page attributes instead of the page ID for the if statement to minimize issues with deleting a page and trying to find its page ID again, but it IS all server side. No JS. :-D
phpQuery website:http://code.google.com/p/phpquery/...
global $first; $class($first<=1)?" class='first'":""; $first++;
When I was searching for the solution last time Jordan pointed me towards a getTotalBlocksInArea function. I didnt fully understand then but I believe you can take the area "contain_sections" and use it within your controller, the new class will retain all the block information about that area. (im not certain about this its all theory)
Meaning you can then to loop over the blocks in the area, filtering by Handle to retrieve only the ones you need.
You could then add these to an array check the index and if [0]?
If you add it to the controller it could be run on a $obj->isFirst();
**edit just noticed its mentioned in option 4 from BoomGraphic
All I know is that it works for that particular purpose.