Advanced Theme Development: Part One

Designer Content, Page List templating

The content block is great for free form content, but if you have something very design centric, it’s better to create a new block type. The Designer Content block found here in the marketplace, is a good starting point for creating new blocks. So let’s add that to our account and install the package (If you are new to installing packages, check out this documentation.) 

designer-content-interface.jpg

Before we get started, make sure your blocks directory is writable: For some information regarding setting directory permissions, check out this documentation

Back in the Designer Content interface, we will give our new block the handle home_featured_story, and the name Home Featured Story. 

All these blocks have a headline, so let’s add a text field call a headline by clicking the text box link. Then we have an image, so let’s add an image field. You can even make the image autocrop and resize to fit with a target width and target height.

Next we will add a “WYSIWYG” editor (A TinyMCE instance), and finish off with a Page Link, a field that lets you link to a particular page within the site (this will give your user the page picker helper to use). Click “Make The Block!” and the block will be created. 

Now when we visit the block types area of the dashboard, we’ll see our new block type. If you look in your site root blocks directory, you will see that there is a directory in there named after your block that has all the relevant files. Pretty cool!

Now we can go back into our themes and replace those content blocks with our new Home Featured Story block. You can populate the block with your own custom headline, image, content, and page link to one of your site pages. But our block doesn’t have the fancy styling our content block had. That’s because we need add our html and styles to the blocks view file. (Currently, the block is just spitting out the raw html of its input). 

So at this point, we'll head to the blocks directory in our site root, and find our block.

designer-block-location.jpg
 
Let's open up its view.php file: 

<?php  defined('C5_EXECUTE') or die("Access Denied.");
$nh = Loader::helper('navigation');
?>

<?php  if (!empty($field_1_textbox_text)): ?>
	<?php  echo htmlentities($field_1_textbox_text, ENT_QUOTES, APP_CHARSET); ?>
<?php  endif; ?>

<?php  if (!empty($field_2_image)): ?>
	<img src="<?php  echo $field_2_image->src; ?>" width="<?php  echo $field_2_image->width; ?>" height="<?php  echo $field_2_image->height; ?>" alt="" />
<?php  endif; ?>

<?php  if (!empty($field_3_wysiwyg_content)): ?>
	<?php  echo $field_3_wysiwyg_content; ?>
<?php  endif; ?>

<?php  if (!empty($field_4_link_cID)):
	$link_url = $nh->getLinkToCollection(Page::getByID($field_4_link_cID), true);
	$link_text = empty($field_4_link_text) ? $link_url : htmlentities($field_4_link_text, ENT_QUOTES, APP_CHARSET);
	?>
	<a href="<?php  echo $link_url; ?>"><?php  echo $link_text; ?></a>
<?php  endif; ?>

You can see there’s only the essential HTML included, an a tag for the link for instance. So we need to plug in the relevant HTML, classes, and ID’s from our theme. Creating views for blocks is a fundamental and very powerful aspect of concrete5. The Designer Content block gives you a great starting point for studying block anatomy by providing block files to analyze, including the view, the controller, the db.xml file, etc.

Once we have customized the view of our block with the relevant bits from our theme, it will look more like this: 

<?php  defined('C5_EXECUTE') or die("Access Denied.");
$nh = Loader::helper('navigation');
?>

<?php  if (!empty($field_1_textbox_text)): ?>
	<h2><?php  echo htmlentities($field_1_textbox_text, ENT_QUOTES, APP_CHARSET); ?></h2>
<?php  endif; ?>

<?php  if (!empty($field_2_image)): ?>
	<div class=”imgholder”><img src="<?php  echo $field_2_image->src; ?>" width="<?php  echo $field_2_image->width; ?>" height="<?php  echo $field_2_image->height; ?>" alt="" /></div>
<?php  endif; ?>

<?php  if (!empty($field_3_wysiwyg_content)): ?>
	<?php  echo $field_3_wysiwyg_content; ?>
<?php  endif; ?>

<?php  if (!empty($field_4_link_cID)):
	$link_url = $nh->getLinkToCollection(Page::getByID($field_4_link_cID), true);
	$link_text = empty($field_4_link_text) ? $link_url : htmlentities($field_4_link_text, ENT_QUOTES, APP_CHARSET);
	?>
	<p class = “readmore” <a href="<?php  echo $link_url; ?>"><?php  echo $link_text; ?></a></p>
<?php  endif; ?>

You can see we are basically wrapping the output in elements, including a an h2 tag, a div with a class of "imgholder", and a p tag, respectively, with a class on the p tag of “readmore”.  

Keep in mind that the blocks that Designer Content creates are standalone, so you could also include them in a package later if you liked. They are not dependent on having the Designer Content package installed. 

This is a good solution for more static content structures, but if these were sections of content that changed a lot, this might not be the best way to do it, since we’d have to create a new block for each new bit of content. A more dynamic and maintainable solution in this situation would be to use the Page List block. So let’s delete these Home Featured Content blocks and head into our home page template. Let’s delete the 3 areas we created for those home boxes and create a new area called “Home Featured Articles”. Now we have one large area instead of 3 smaller areas. 

We want this to pull the 3 most recent pages from under a certain page, and from those pages, only ones that we actively choose to feature on the home page. The Page List block has a built-in option to filter pages by the page attribute "is_featured". So first let’s create a new page attribute for featured pages. Head over to /dashboard/pages/attributes.

page-attributes.jpg

Head to the bottom of the page and add an attribute of the "checkbox" type. Use the handle "is_featured" and name it Featured Page. Make sure you get the handle correct, as the Page List block is looking for exactly that handle.   

Now when we go to a page’s properties, we can set this as a custom attribute.  

feature-page-option.jpg

Make sure when you apply the attribute you also check the box to make the attribute active for the page. 

For other attributes, you usually have to write a bit of code to access them, but the Page List block automatically interfaces with this attribute, so we’re good to go. Let's add a Page List block to our area "Home Featured Articles" and set the following options: 

  • Display 3 pages of type “all”. 
  • For filter, let’s switch off display page aliases to increase the speed of the query. 
  • We will leave pagination unchecked, since we don’t want it to appear. 
  • For location in website, we will tell it to pull pages from underneath the “about” page, in this case. 
  • For Sort Pages, we will choose “most recent first.” 
  • We won’t use RSS. 
  • We won’t mess with the summary truncation. 

Now let’s set up our pages under "about" that we want to appear with the is_featured page attribute. Once we do that, you will see them showing up on the site. However, they won’t look quite right, because the page list outputs its own HTML. We need to integrate this into our theme. We will do this by creating a custom template for the page list block. 

Custom templates are powerful tools that let you create view layers for blocks. They also allow you to customize block views without messing with other essential block code. They also survive updates, so your block view customizations will persists through updates. First, we need to find the name of the of the directory of the block in the core we want to template, in this case page_list. Then we create a folder in our root blocks directory called page_list. Inside that folder, we create another folder called “templates”, and in there make a directory and name it after our template. Now we need to grab the the view.php file of the page list block in the core to use as a starting point, and throw it in our overridden template directory. We will find this in our concrete directory, in concrete/blocks/page_list/view.php. Copy that (remember never to edit core files, always override them) and paste that in our template directory. 

directory-structure.jpg

Whew! All right, let’s start editing our template now. We can remove some bits that we don’t need since this template is very specific to our site, including the pagination, so we delete this bit: 

<?php if ($showPagination): ?>
	<div id="pagination">
		<div class="ccm-spacer"></div>
		<div class="ccm-pagination">
			<span class="ccm-page-left"><?php echo $paginator->getPrevious('&laquo; ' . t('Previous')) ?></span>
			<?php echo $paginator->getPages() ?>
			<span class="ccm-page-right"><?php echo $paginator->getNext(t('Next') . ' &raquo;') ?></span>
		</div>
	</div>
<?php endif; ?>

And we also don’t need the RSS Icon, so we can also delete this bit:

	<?php if ($showRss): ?>
		<div class="ccm-page-list-rss-icon">
			<a href="<?php echo $rssUrl ?>" target="_blank"><img src="<?php echo $rssIconSrc ?>" width="14" height="14" alt="<?php echo t('RSS Icon') ?>" title="<?php echo t('RSS Feed') ?>" /></a>
		</div>
		<link href="<?php echo BASE_URL.$rssUrl ?>" rel="alternate" type="application/rss+xml" title="<?php echo $rssTitle; ?>" />
	<?php endif; ?>

And now, we will change out the html output in the view to match our theme. So let’s make sure it starts with an unordered list. We’ll place a ul right after <div class="ccm-page-list"> in our view. Then within the foreach loop, we’ll want to create a list element for each page and place the page title within an h2 tag (we can remove the link from it in this case, because we don’t need it on this tag). We’ll skip the image for now, but come back to it. Let’s just put in the div with the class “imgholder” for now. We will put the description of the page in a p tag. And finally, we will add in the read more link, a p tag with a class of “readmore” and the text “Continue Reading”. Here’s how this will all look when we're done:

<li>
<h2><?php echo $title ?></h2>
<div class=”imgholder”></div>
<p><?php echo $description ?></p>
<p class=”readmore”><a href = “<?php echo $url ?>”>Continue Reading &raquo;</a></p>
</li>

Now, we need to apply our custom template to the page list block. We do that by clicking the page list block in edit mode and choosing “Custom Templates.” You’ll see there are already two that ship with the core in there, Blog Index and Blog Index Thumbnail. We will select ours, Home Featured Stories. Other packages can also add custom templates for blocks as well. 

It looks like we have a class of “last” that is applied to the first and last li tags dictated in our theme. So we’ll need to set up an iterator to apply this to the last list element in our series. So we will set a variable just before the foreach loop, like so: 

$i = 0;

Just inside the foreach, set that variable incrementing like so: 

$i++ 

Since we know that in our theme, there are only 3 elements across, we will set this to echo out the class “last” on the third list item like so: 

<li <?php ($i == 3) {?>class=”last” <?php } ?>>

This will apply the class to every third li tag, which should get our page list template looking correct in our theme. 


Recent Discussions on this Topic

Keep Theme Styles from Interfering with concrete5

Can someone please explain this to me, as I have a few sites that I have built where the theme does interfere with the Concrete5 Interface. ----------------------- From C5 Documentation: Keep Theme Styles from Interfering with concrete5 When c…

how to call the controller from theme header

Hi, I am developing web application by using the concrete5, First i try to implement multilingual in single pages, its work sample i attached my screen shots image. pfa. Now i want to this in my theme, how to do this. experts help me. than…

Render page without theme

Hi Is it possible render page without theme? I'm building my own package for concrete5 and I want to render basic html-view. So I don't want any theme files there. Is it possible? Now I'm trying in controller.php public function view() { $…

Problem with the nav bar with bootstrap

Hey guys, finishing up my site here. The one issue I'm having is having the navigation load normal. The original code is: Toggle navigation Ambrosia …

Package attribute

For a new theme I want to have a pagelist install with it which shows up thumbnails of pages, I have this all sorted but I have no idea how to install the 'thumbnail' attribute with my theme, I have looked at other packages but cant find any examples wher…