How to enable cover image on the front-end?

Hi hello. I am still learning Kirby as I develop my own site based off a template that I created previously. I am having issues with connecting new field in Blueprint to the front-end bit.

Thanks in advance for your help!

http://www.practice.studio/src/

Project Blueprint

title: Project
pages: true
files:
  sortable: true
fields:
  title:
    label: Title
    type:  text
  year:
    label: Year
    type:  text
  text:
    label: Text
    type:  textarea
  tags:
    label: Tags
    type:  tags
  coverImage:
    label: Cover Image
    type: image

Projects Snippet

<div id="projects">

    <div class="grid"></div><div class="gutter"></div>
    
    <?php foreach($projects as $project): ?>
        
        <div class="thumbs">
            <a class="thumbs-info" href="<?php echo $project->url() ?>">
                <span class="thumbs-tag"><?php echo $project->tags() ?></span>
                <span class="thumbs-title"><?php echo $project->title()->html() ?></span>
            </a>
            
            <?php if($image = $project->images()->sortBy('sort', 'asc')->first()): ?>
            
                <a href="<?php echo $project->url() ?>">
                    <img src="<?php echo $image->resize(1280,null,70)->url() ?>" alt="<?php echo $project->title()->html() ?>" >
                </a>
            
            <?php endif ?>
        
        </div>
        
    <?php endforeach ?>

</div>

You mean, instead of fetching the first image, you want to get the cover image? Then you can do it like this:

<?php if($image = $project->coverImage()->toFile()): ?>
  // rest of code
<?php endif ?>
1 Like

You understood me perfectly despite the haziness of my question. That worked like a charm, thanks man.

Actually, I might piggyback on this question for another issue I am trying to figure out.

I want to make an exception from the masonry I set up for posts that only has one image to show, e.g. http://www.practice.studio/src/projects/001

I can sort of understand what needs doing but can’t code it up myself, basically I need to make an if statement that would disable masonry (or refer to 100% grid width) if there is only one image. Is this possible with the current state of code I have, or would I need to set up something new?

Project snippet

<div class="project-info">
    <h3><?php echo $page->title()->html() ?></h3>
    <text><?php echo $page->text()->kirbytext() ?></text>
</div>
    
<div id="images">    
    
    <div class="grid"></div><div class="gutter"></div>
    
    <?php 
    $projectPages = page('projects')->children()->visible();
    $projectImages = $projectPages->files();
    
    foreach($page->images()->sortBy('sort', 'asc') as $image):
    ?>
    
    <div class="images">    
        <img src="<?php echo $image->url() ?>">
    </div>
    
    <?php endforeach ?>
    
</div>

I think the easiest way would be to just give the grid a second class, something like 'single-image", and then exclude this class from your masonry call?

$('.grid:not(.single-image)').masonry({
  // options
});

Unfortunately I am not sure if I follow. Above solution would be JS focused, meaning I’ll need to modify my main.js file, yeah?

Right, both your JS file, where you make the masonry call, and the snippet where you add the class depending on whether or not the page has a cover image.

I’m lost as this is not related to cover image at all.

I’ll try rephrasing my question.

Project with multiple images uploaded: http://www.practice.studio/src/projects/bowen-arico
Project with single image uploaded: http://www.practice.studio/src/projects/20160822

You can see that masonry is enabled for both, what I’d like to figure out is to how stop masonry being applied to projects that only has one image.

Files/code associated to this:

main.js

$(document).ready(function() {

    // init Masonry for Index
    var $grid = $('#projects').masonry({
      columnWidth: '.grid',
      itemSelector: '.thumbs',
      percentPosition: true,
      gutter: 0,
    });
    
    // init Masonry for Project
    var $grid = $('#images').masonry({
      columnWidth: '.grid',
      itemSelector: '.images',
      percentPosition: true,
      gutter: 0,
    });

    // layout Masonry after each image loads
    $grid.imagesLoaded().progress( function() {
      $grid.masonry('layout');
    });
    
    // Initializie infinite scroll

    var ias = jQuery.ias({
      container:  '#projects',
      item:       '.thumbs',
      pagination: '#pagination',
      next:       '.next',
      delay: 0
    });

    ias.extension(new IASSpinnerExtension({
      html: '<div class="ias-wrapper"><div class="ias-spinner" style="text-align: center; position: absolute; bottom: 2em; left: 50%; transform: translateX(-50%) translateY(100%);"></div></div>',
    }));

    // Hide new items while they load + relayout masonry when new items are added

    ias.on('render', function(items) {
      $(items).css({ opacity: 0 });
    });

    // Append new items to exisiting masonry grid


    ias.on('rendered', function(items) {
      $grid.imagesLoaded( function() {
        $grid.masonry( 'appended', items )
      });
    });
  
});

project.php snippet

<div class="project-info">
    <h3><?php echo $page->title()->html() ?></h3>
    <text><?php echo $page->text()->kirbytext() ?></text>
</div>
    
<div id="images">    
    
    <div class="grid"></div><div class="gutter"></div>
    
    <?php 
    $projectPages = page('projects')->children()->visible();
    $projectImages = $projectPages->files();
    
    foreach($page->images()->sortBy('sort', 'asc') as $image):
    ?>
    
    <div class="images">    
        <img src="<?php echo $image->url() ?>">
    </div>
    
    <?php endforeach ?>
    
</div>

Sorry for the hassle! Hope I’ll understand and be able to get it running correctly after next round of answer.

Ok, thanks for clarifying, this should work then:

In your snippet, add the class to the element you are calling the masonry function on (#images).

<div class="project-info">
    <h3><?php echo $page->title()->html() ?></h3>
    <text><?php echo $page->text()->kirbytext() ?></text>
</div>
<div id="images" <?php e($page->images()->count() == 1, 'class="single-image"', '') ?>>    
    <div class="grid"></div><div class="gutter"></div>
    <?php 
    $projectPages = page('projects')->children()->visible();
    $projectImages = $projectPages->files();
    foreach($page->images()->sortBy('sort', 'asc') as $image):
    ?>
    <div class="images">    
        <img src="<?php echo $image->url() ?>">
    </div>
    <?php endforeach ?>
</div>

In your js, exclude all divs with class “single-image”:

var $grid = $('#images:not(.single-image)').masonry({
  columnWidth: '.grid',
  itemSelector: '.images',
  percentPosition: true,
  gutter: 0,
});
```

Ah, I can see how it works out. Though I did try implementing, it came back with an error which is visible on http://www.practice.studio/src/projects/20160822

Warning:  count() expects at least 1 parameter, 0 given in /home/ravivasavan/practice.studio/src/site/snippets/project.php on line 6

replace this with ->count() that should do the trick.

Nice, the error is now gone. Can’t believe I didn’t catch that missing >.

Now to figure out why it’s not firing right yet. Maybe I need to do some CSS!

You mean the overlapping images on your frontpage?

Maybe this fixes your issue.

// layout Masonry after each image loads
$grid.imagesLoaded().progress( function() {
  $grid.masonry('layout');
});

Because it looks like, the masonry does not adjust correctly to loading images. Only after page-resize it places the images at the right position…

EDIT nevermind, all included in your main.js :smiley: did’t see that ;D

Haha no problems.

The actual issue is that I wanted projects with multiple images to be 2 columns (grid set at 50%) as previously set up but now it’s 1 column (grid set at 100%).

Example:

http://www.practice.studio/src/projects/001 - this page is meant to be 100% as there is only 1 image for the project.

http://www.practice.studio/src/projects/bowen-arico - this page is meant to be showing the 50% grid as there are more than 1 image.

I thought the solution above would help with that. Feel like I am missing something here.

Check your markup.

This might be the problem :slight_smile: or one of them…

<div class="grid"></div><div class="gutter"></div>

Should be

<div class="grid">
  <div class="gutter">
    <?php 
      $projectPages = page('projects')->children()->visible();
      $projectImages = $projectPages->files();
      foreach($page->images()->sortBy('sort', 'asc') as $image):
    ?>
      <div class="images">    
        <img src="<?php echo $image->url() ?>">
      </div>
    <?php endforeach ?>
  </div>
</div>

Btw. nice art :slight_smile:

Thanks man, I’m a-ok designer/art director and a terrible developer. :smiley:

With your help and some mad editing at my end, got it all working.

Single image: http://www.practice.studio/src/projects/osaka
Multiple images: http://www.practice.studio/src/projects/bowen-arico

Now to fix the imagesLoaded issue, if you can spot my errors there, let me know as I haven’t really used imagesLoaded in the past!

After that, the site is 99% done. The 1% is to re-do all of the images, haha.

Check you other pages for the same mistake :slight_smile:

As stated previously, I am a terrible developer.

Fixed that for the projects snippet. It should behave better now, onto figuring out infinite scroll with ias.js :sweat: