Jump to content

3 cols of featured content - best practice


Peter Knight
 Share

Recommended Posts

Hi 

I have an area on every page of my site which includes 3 columns of "featured" content as determined by my client.

Each feature consists of:

  • A page title (and link to parent page)
  • An image
  • Small paragraph of summary text

post-1166-0-97381500-1407854804_thumb.pn

I know that I must add these fields to my pages and then populate them with content. The part i'm stuck at is how best to let client my determine which 3 pages get featured. I think number 3 here is the best way but wanted to ask more seasoned users their approach.

Should I ...

1. Create some mechanism for a client to specify a page as "featured" thereby triggering inclusion into a footer. I'd have some API call scanning pages for a checked "featured" checkbox etc

or

2. Create 3 small sub-pages elsewhere on the site consisting solely of the title,image,paragraph fields. I could place them in some kind of sub-folder called "featured". My client would be told to only ever have 3 sub pages and they could edit, rearrange etc

or

3. Create a single page called "Featured" consistign of the new ProField Table whereby client can order and reorder as they wish. That ProField Table would be a row consisting of "Title", "Image" and "Summary".

Link to comment
Share on other sites

my favourite 2 ways are by no specific order:

1. Add a "featured" checkbox to each page and show the last 3: $pages->find('featured=1, sort=-date, limit=3');

2. Add a page field in the homepage where your client can add pages, and show the top 3 from that field.

  • Like 5
Link to comment
Share on other sites

Thanks diogo

There's just too many ways to do this in PW. Guess thats the beauty of it! :)

1. Add a "featured" checkbox to each page and show the last 3: $pages->find('featured=1, sort=-date, limit=3');   

That would certainly work. Would my client be able to reorder the sequence of featured items though? They could be from very disparate areas of the site.

2. Add a page field in the homepage where your client can add pages, and show the top 3 from that field.

Thank you for introudcing me to the page field! I hadn't seen it before and watching this, I can't believe how simple and powerful it will be for my client.

I've purchased ProFields anyway but I'm sure I'll find a use for it :)

Link to comment
Share on other sites

That would certainly work. Would my client be able to reorder the sequence of featured items though? They could be from very disparate areas of the site.

No, this suggestion is just the one that I consider really simple, but it's less flexible for sure. If you want the client to be able to reorder them, use my second suggestion instead.

I've purchased ProFields anyway but I'm sure I'll find a use for it :)

Oh, you will :) This is one of the most important fields in PW. ProFields are great, but they are for sure no replacement to the page field. And since you haven't seen this kind of field before I strongly suggest that you read this tutorial by Kongondo https://processwire.com/talk/topic/3579-tutorial-approaches-to-categorising-site-content/

Link to comment
Share on other sites

Cheers. Looks pretty comprehensive and I've got the printer working it's way through it.

Could you point me in the direction of how to output fields from my selected pages?

I've created a page field, added it to my template and then on my actual page, I have selected my 3 pages. That was all remarkably straighforward. But how do I get the field values I want out onto a different page?

foreach ($page->pattern_type as $pt) {
echo $pt->title;
echo $pt->featured-image;
echo $pt->featured-summary;
} 

Should I replace "pattern_type" as my Pages Field name?

Link to comment
Share on other sites

Should I replace "pattern_type" as my Pages Field name?

Yes.

If you added the field to the homepage, spitting the first 3 pages on the home is as easy as:

foreach ($page->pageField->find('limit=3') as $pt) {
    echo $pt->title;
    echo $pt->featured-image;
    echo $pt->featured-summary;
} 

If you want to do the same in any other page use instead:

$pages->get(1)->pageField->find('limit=3')
Link to comment
Share on other sites

Also something that I have been working on is the option to allow the client to change their mind and decide that maybe this month they want 4 or 6 featured items. In that case you can just take all, count them and run an if else decision to allow for different div layouts. I am up to 6 different main layouts with special blocker divs for odd numbered layouts. Let me know if you need any sample code to get you goin :) 

Link to comment
Share on other sites

I've done something similar with a Top10 of destinations a client of mine wanted in her travel site.

But I used just an integer field in the destination template in which she could put a number 1 to 10.

That worked for her, but it's also up to her to take care that she has all the numbers from 1 to 10 only once.

She can check easily in the site itself if she has the numbers correct.

From all the info in the destination pages only the title, url, and first image are used.

The php in the template looks like this (for the first 5 pagelinks):

All the html depends afcourse on the design you want.

$top1to5 = $pages->find("template=hotel, top10>0,sort=top10,limit=5");
echo "<div class=\"top10table\">";
foreach($top1to5 as $top) 
  {
  echo "<div class=\"top10row\">";  
  echo "<div class=\"top10name\"><a href='{$top->url}'>{$top->title}</a>></div>";
  $image = $top->foto_upload->first();
  if (!$image){
  $image = $pages->get('/')->foto_upload->first();  
  }
  $thumb = $image->size(70, 70);
  echo "<div class=\"top10image\"><img src='$thumb->url'></div>";
  echo "</div>";
  }
echo "</div>";

This script is in the header template that is included in all the pages.
You can see the result at www.travelinluxury.nl. Click on the arrow under Top 10 in the upper right corner.

With the arrow under the first 5 you get to the next 5 for which I use a similar script as above.

Link to comment
Share on other sites

//=======================================================//
//           MAGICAL BOOTSTRAP DIV GENERATOR             //
//		   COPYRIGHT 2014--MUCHDEVELOPMENT.COM           //
//=======================================================//	
//Settings page has integer box to override image width \\\
if ($page->ImageWidthOverride){
$imageWidth = $page->ImageWidthOverride;	
} else {
$imageWidth = 400;
}

$bootstrapDivs = "";
$generateFeatured = true;

if($featuredCount>=5){
$bootstrapDivs = "col-sm-2";
$blankColumn = "<div class='col-sm-1'></div>";
}else if ($featuredCount ==  4){
$bootstrapDivs = "col-lg-3 col-sm-5";	
$specialWrapperStart = "<div class='specialCenter'>";	
$specialWrapperEnd = "</div>";				
}else if ($featuredCount == 3){
$bootstrapDivs = "col-sm-4";
}else if ($featuredCount == 2){
$bootstrapDivs = "col-sm-6";
$specialWrapperStart = "<div class='specialCenter'>";	
$specialWrapperEnd = "</div>";				
}else if ($featuredCount == 1){
$bootstrapDivs = "col-xs-12";
$specialWrapperStart = "<div class='specialCenter'>";	 
$specialWrapperEnd = "</div>";				
}else{
$generateFeatured = false;			
}


$top .= '<section class="container articles">';
//$top .= '<div class="spacer"></div>';
$top .= '<div class="spacer"></div>';
$top .= $blankColumn;
foreach ($featuredPages as $article){
	$thisImageWidth = $imageWidth;
	if ($article->specialWidth){
		$thisImageWidth = $article->specialWidth;
	} 
	$top .= $specialWrapperStart;				
	$top .="<div class='{$bootstrapDivs} articleholder'>";
	$top .='<div class="article">';
	$top .="<strong class='articleCardTitle'>{$article->title}</strong>";
	$top .="<div class=''><img class='exhibitionFeaturedCardImg' src='{$article->article_thumbnails->width($thisImageWidth)->url}'></div>";
	$top .="<div col-xs-12><strong class='cardName'>{$article->article_metadescription}</strong></div>";
	$top .="<p>{$article->article_dateOpen}</p>";
	//$top .="<p>{$article->article_introtext}</p>";
	$top .="<a class='btn btn-default' href='{$article->url}'><strong>Click here to view this exhibition</strong></a>";
	$top .="</div>";
	$top .="</div>";
	$top .= $specialWrapperEnd;					
}//end of featured loop
$top .= $blankColumn;

$top .='</section>';
$top .='<hr/>';
$top .='';

echo $top;
}//end of if generateFeatured

//end of featured


So by counting how many there are I then print the div structure using this for my logic. A bit messy and not quite everything, but I thought it was pretty cool. Oh and dont worry, they copyright is a joke, use it if you find any use for it :)

Link to comment
Share on other sites

I have this working now with the three columns I want  :).

I basically select the three pages from a page field on the homepage called "Featured_Content". Each of those pages has a title, image and summary.

<div class="layer layer-is-featured">
      <div class="row">
      
<?php foreach ($pages->get(1)->Featured_Content->find('limit=3') as $featured){echo "
        <div class='small-12 medium-4 columns'>
           <img src={$featured->images->first()->url} />
           <h3 class='feature-heading'>{$featured->title}</h3>
             {$featured->summary}
             <a href='#'>Read more</a>
        </div>
";} ?>
      </div>
</div>
I'm wondering what the best way to crop each featured image to a specified dimension would be.
 
If I ask my client to ensure each image is 330 x 158, she's going to mess this up.
 
This looks like it might be my solution (http://modules.processwire.com/modules/fieldtype-crop-image/) but I'd rather specify in the code that each image should be cropped to 330 / 158.
 
I have read through the ProcessWire image API docs (http://processwire.com/api/fieldtypes/images/) but I'm not sure how to combine this with my code above.
 
foreach($page->images as $image) {
 $large = $image->width(500); 
 $thumb = $image->size(100, 100); 
 echo "<a href='$large->url'><img src='$thumb->url'></a>";
}
  • Like 1
Link to comment
Share on other sites

So Im a pretty big fan of the thumbnail generator. You can change image field to use it and then the field will act exactly the same except then you can talk to it like this. Just define that thumbnail is the resolution of the thumbnail that you want to use. Then if you want to be extra safe from the medling hands of your client add a class to your css:

.medlingClient{
width:330px; 
height:158px;
}
<img class="medlingClient" src={$featured->images->first()->getThumb('thumbnail')} />

How's this look?

  • Like 1
Link to comment
Share on other sites

By "the thumbnail generator", you mean the module I linked to above by apesia?

Looks very cool. Thanks for the recommendation.

:) Yeah thats what I meant, sorry late night. So anyway check that module out an give it some tinkering. Its an amazing tool.

Link to comment
Share on other sites

I am getting an eror of:

Error: Call to a member function getThumb() on a non-object (line 7 of /Users/macbook/Sites/ProjectX/site/templates/includes/get-featured.inc) 
This error message was shown because you are logged in as a Superuser. Error has been logged.

I think everything is set up correctly.

  • I created an image field with the appropriate "CoprImage" type
  • assigned it to the 3 pages I am calling content from
  • setup a crop called "featuredimage" and set the settings to 
    thumbnail,100,100
    featuredimage,330,158
  • cropped the images manually via the popup crop interface and hit save

So based on my pervious working code which displays fullsize images, this

<div class="layer layer-is-featured">
      <div class="row">
	<?php foreach ($pages->get(1)->Featured_Content->find('limit=3') as $featured){echo "
        <div class='small-12 medium-4 columns'>
	<img src={$featured->images->first()->url} />
        <h3 class='feature-heading'>{$featured->title}</h3>
          {$featured->summary}
          <div class='divider'></div>
          <a href='#'>Read more</a>
        </div>
		";} ?>
      </div>
</div>

should change to this

<div class="layer layer-is-featured">
      <div class="row">
<?php foreach ($pages->get(1)->Featured_Content->find('limit=3') as $featured){echo "
        <div class='small-12 medium-4 columns'>
                <img src={$featured->images->first()->getThumb('featuredimage')} />
        <h3 class='feature-heading'>{$featured->title}</h3>
          {$featured->summary}
          <div class='divider'></div>
          <a href='#'>Read more</a>
        </div>
";} ?>
      </div>
</div>

What does this actually mean?

Call to a member function getThumb() on a non-object 

Link to comment
Share on other sites

I am getting an eror of:

I think everything is set up correctly.

  • I created an image field with the appropriate "CoprImage" type
  • assigned it to the 3 pages I am calling content from
  • setup a crop called "featuredimage" and set the settings to 
    thumbnail,100,100
    featuredimage,330,158
  • cropped the images manually via the popup crop interface and hit save

So based on my pervious working code which displays fullsize images, this

<div class="layer layer-is-featured">
      <div class="row">
	<?php foreach ($pages->get(1)->Featured_Content->find('limit=3') as $featured){echo "
        <div class='small-12 medium-4 columns'>
	<img src={$featured->images->first()->url} />
        <h3 class='feature-heading'>{$featured->title}</h3>
          {$featured->summary}
          <div class='divider'></div>
          <a href='#'>Read more</a>
        </div>
		";} ?>
      </div>
</div>

should change to this

<div class="layer layer-is-featured">
      <div class="row">
<?php foreach ($pages->get(1)->Featured_Content->find('limit=3') as $featured){echo "
        <div class='small-12 medium-4 columns'>
                <img src={$featured->images->first()->getThumb('featuredimage')} />
        <h3 class='feature-heading'>{$featured->title}</h3>
          {$featured->summary}
          <div class='divider'></div>
          <a href='#'>Read more</a>
        </div>
";} ?>
      </div>
</div>

What does this actually mean?

Call to a member function getThumb() on a non-object 

Sorry for some reason alerts did not show up for me on this one. You get it figured out? Looks like you are pointing that method to an object that doesnt have an image is my guess. Did you maybe change the field to max of 1 image? In that case I know you wouldn't need ->first() as that function just pulls the first in an array. Also I would read up on find() as you could probably locate those pages a little easier that way. 

Link to comment
Share on other sites

Hey uprightbass360

I was literally about to post an update when your latest post apepared.

After days of getting nowhere and a looming deadline, I wondered if perhaps my issues were a result of a local environment so I reinstalled PW on my www hosting, setup all the same fields, templates, pages etc (zzzz) and the same code worked beautifully.

The only changes I actually made were to set a max of 1 image on the image field. I think there was something locally preventing me from using CropImage properly on my local install. I can tell now because when I crop an image on my remote site, the image in the "featured_image" field reflects the cropped image. On my local install, the image was allegdely cropped but always displayed the fullsize image with the image field. 

Whew! Anyway, I'm finally moving forward again and building my clients site. Thanks everyone for the help.

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...