# Content Groups in Layout Descriptor

This article details the customization options offered by the layout descriptor for content groups. The Content Group Layout extends the default Layout and Layout Attributes and adds fields to easily configure them.

There are specific core mixins available to style a content group.

# Declare a Content Group

A content group is always declared with the name balcon instead of a layout name:

"layouts": [
  {
    "name": "balcon",
    ...
  }
]

Balcon?

Balcon is the deprecated name for Content Groups. You will find it widely used in the codebase.

There are 2 ways to declare a Content Group's layout:

# balconLayout

balconLayout lets you reuse Content Groups already defined in Marfeel codebase.

Content group templates are stored in a special balcon folder, in Marfeel's default theme (opens new window). For example:

themes/default/balcon/balcon_photo_slider.jsp

To reference a template, drop the balcon_ prefix:

"layouts": [
  {
    "name": "balcon",
    "attr": {
      "count": 4,
      "balconLayout": "photo_slider"
    }
  }
]

Refer to the Content Groups catalog, to know what is available.

Dependencies

The layouts that a predefined content group depends on (here photo/photo and photo/photo_slider) must be added to an extraLayouts.json file.

# layouts

layouts lets you define custom Content Groups, where you specifically define each layout it will use:

"layouts": [
  {
    "name": "balcon",
    "attr": {
      "layouts": ["newspaper/thumb", "photo/photo"],
      "count": 2
    }
  }
]

In its simplest form, layouts is an array of strings, containing all the layouts used for the content group. You can combine any existing layout into a Content Group.

layouts can also become more complex, just like the main layouts object of the content group:

"layouts": [
  {
    "name": "balcon",
    "attr": {
      "layouts": [
        "newspaper/thumb",
        {
          "name": "photo/photo_grid_2",
          "attr": {
            "count": 2
          }
        }
      ],
      "count": 3
    },
  }
]

# Fill a Content Group with articles

Content groups are available with any ripper (WhiteCollar, JSOUP...), but it is optimized for the WhiteCollar.

# Top-level section

For all rippers, you can select which articles fit in a content group with the section property.

Use the section name value from the definition.json file to get articles from that section fed into a Content Group:




 










"layouts": [
  {
    "name": "balcon",
    "section" : "sports",
    "attr": {
      "count": 4,
      "pocket" : {
        "balconLayout": "slider",
        "title" : "Sports news"
      }
    }
  }
]

# section inside pocket

With the MarfeelPressRipper, sections that are not in definition.json are also available. Declare the section name nested inside the pocket object:

MarfeelPressRipper uses the value to find the articles associated with this category or tag as fallback.

It is equivalent to the WhiteCollar key method, and used the same way in the backend which is why it requires a key property, identical to the section value:




 




 






"layouts": [
  {
    "name": "balcon",
    "key" : "sports",
    "attr": {
      "count": 4,
      "pocket" : {
        "balconLayout": "slider",
        "section" : "sports",
        "title" : "Sports news"
      }
    }
  }
]

# Top-level key

The WhiteCollar can group items by key. Use those groups in the layout descriptor with the corresponding key property:

{
    "name": "newspaper/thumb_card",
    "key": "most-read"
}

# key operations: startsWith

You can prefix the value by startsWith:. It retrieves all the groups which key has a common prefix.

For example, this selection will retrieve all the groups which key starts with news-, such as news-sports, news-movies, news-politics...:

"layouts": [
  {
    "name": "balcon",
    "key": "startsWith:news-",
    "attr": {
      "balconLayout": "photo_slider"
    }
  }
]

With this feature, the layout is repeated for each group of items separately. In this case, we obtain 3 different sliders.

The order of rendering between content groups in the same startsWith block is defined by the items extraction.

AdDealer and `startsWith`

You can’t manually control ads display between content groups using the startsWith feature. The only way to render an ad between those content groups is by activating the adDealerMosaic flag in features.json.

WhiteCollar extensiblity

With this feature, when a tenant adds or modifies an existing content group on their website, we only need to update the item selection in the WhiteCollar. The rendering will work out-of-the-box for the new selection.

# count

This attribute is valid for any layout but is mandatory for content group. It is particularly important for layouts where the amount of items is not fixed, such as a slider:

{
  "name" : "balcon",
  "key": "people",
  "attr": {
    "count" : 8
  },
  "pocket": {
    "balconLayout": "slider"
  }
}

# Content Group title

A Content Group can have a visible header if one of these conditions is met:

  • A section is defined: the Content Group header will be the section's title (as defined in definition.json).
"layouts": [
    {
        "name": "balcon",
        "section": "someSection"
        ...
    }
]
  • The pocket contains a title property: the Content Group header will use it.
"layouts": [
    {
        "name": "balcon",
        ...
        "attr": {
            "pocket": {
                "title": "Example title"
            }
        }
    }
]

Hide the Content Group header with the showTitle attribute if it is undesirable:

"layouts": [
  {
    "name": "balcon",
    ...
    "attr": {
        "showTitle": false
        ...
    }
  }
]

# "Ranking" Content Groups

Some content groups are of type "ranking". Those layouts have two optional features, to configure in the pocket:

  • disableCounter: boolean. Default is false. Removes the counter number from the layout.
  • showRankingAd: boolean. Default is false. Adds an ad after the second article.
{
  "layouts": [{
    "name": "newspaper/ranking",
    "attr": {
      "count": 12
    },
    "pocket": {
      "disableCounter": true,
      "showRankingAd": true
    }
  }]
}

# Use an image

The logo property can be defined for any Content Group, replacing the title or supporting it.

The logo can be a svg, png or jpg.

  • Logo with a title:

logo and title as header

{
  ...,
  "pocket": {
    "title": "Group title",
    "img": "https://example.com/files/example-logo.svg",
  }
}
  • Logo instead of a title:

logo only as header

Make sure the title property is a blank space:

{
  ...,
  "pocket": {
    "title": " ",
    "img": "https://example.com/files/example-logo.svg",
  }
}

TIP

UX team usually prepares those logos, if they don’t already have an appropriate size on the tenant’s website.

# Additional class

Optional. You can add a className property inside the attr, which will be appended to the Content Group root in Marfeel:






 



{
  "name": "balcon",
  "attr": {
    "title": "Group Title",
    "balconLayout": "slider",
    "className": "mrfdocs-group"
  }
}

Result in the Marfeel version:

<section class="mrf-balcones slider mrfdocs-group">
  ...
</section>

# ExtraLayouts

When using content groups, extraLayouts.s.json and extraLayouts.xl.json files must be created in LayoutDescriptor folder.

It contains a layouts array, holding a list of layouts, for example:

extraLayouts.s.json

{
"layouts": [
    "photo/photo",
    "photo/photo_slider",
    "newspaper/pill"
  ]
}

extraLayouts.xl.json

{
"layouts": [
    "photo/photo_sky300",
    "photo/photo_slider",
    "newspaper/pill_sky300"
  ]
}

The layouts can be declared in any order, and won't display anywhere. Content groups are usually importing several existing layouts, which have their own CSS. However, we must declare those dependencies for the build system to include those additional CSS files.

It is not necessary to include this file if no content group has hidden dependencies.

Some widely-used content groups benefit from an ad-hoc solution, and it is not necessary to add anything if you use them:

  • newspaper/text_slider
  • newspaper/opinion_slider
  • sliders/tag-slider
  • sliders/pill-slider