Blueprint Developer Manual / Version 2307
Table Of ContentsRequirements
For a good user experience a website should not layout each and every page in a different fancy manner but limit itself to a few carefully designed styles. For example, most pages consist of two columns of ratio 75/25, where the left column shows the main content, and the right column provides some personalized recommendations.
In the best case an editor needs to care only for the content of a page, while the layout and collateral contents are added automatically, determined by the context of the content. However, there will always be some special pages, so the editors must be able to change the layout or the collateral contents. For example for a campaign page which features a new product they may omit the recommendations section and choose a simple one-column layout without any distracting features. In order to preserve an overall design consistency of the site, editors are not supposed to create completely new layouts. They can only choose from a predefined set.
Solution
CoreMedia Blueprint addresses these requirements with the concept of a page grid and placements.
The page grid does not handle overall common page features such as navigation elements, headers,
footers and the like. Those are implemented by Page templates with special views. Neither does
the page grid control the layout of collections on overview pages. This is implemented by
CMCollection
templates with special views and view types.
You can think of a page grid as a table which defines the layout of a page with different sections. Each section has a link to a symbol content item which will later be used to associate content with the section. Technically, the layout of a page is defined in form of rows, columns and the ratio between them. A page grid contains no content and can be reused by different pages. So you might define three global page grids from which an editor can select one, for instance.
The content for the page grid on the other hand, is defined in a CMChannel
content item
in so called placements, realized as link lists in structs. Each placement is associated with a
specific position of the page grid through a link to a symbol content item. The editor can add
content to the placement, collections for example, which will be shown at the associated
position of the page grid.
Placements can also be shared between channels because a child inherits the placements of its parent. A prerequisite for inheritance is that the page grids of the parent and child page must have sections with the same name. For example, the parent channel has a two-column layout with the sections "main" and "sidebar". The child channel has a three-column layout with the sections "main", "sidebar" and "leftcolumn".
For the placements this means:
The child must fill a placement with content for the "leftcolumn" section, because the parent has no such section.
The child will override the placement for the "main" section with its content. Inheritance makes no sense for the "main" section.
The child does not need to declare a "sidebar" placement but can inherit the "sidebar" placement of the parent, even though it uses a different layout.
Before going into the implementation details of the page grid, you will see how to work with page grids in CoreMedia Studio.
Page grids in CoreMedia Studio
Editors can manage pages directly by editing the "placements" in the page grid in
CMChannel
content items (localized as Page
in CoreMedia
Studio). A placement is a specific area on a page such as the navigation bar, the
main column or the right column.
A CMChannel
can inherit page grid placements of
its parent channel. For example, the Sports/Football section of a site can inherit the right
column from the Sports section. Editors can also choose to "lock" certain placements and thus
prevent subchannels from overwriting them. Each page grid editor provides a combo box to choose
between different layouts for a page. Depending on the selected layout, placement may inherit
their content if the same placement is defined in the layout of the parent page.
Each placement link list can configure a view type. The view type determines how the placement is rendered.
To define which placement view types are available for a page in some site, view type
(CMViewtype
) content items are placed in view type folders under a site-relative path
or at global locations. The default paths are the site-relative path
Options/Viewtypes/
and the absolute path
/Settings/Options/Viewtypes/
. This can be configured via the application
property pagegrid.viewtype.paths
, which contains a comma-separated list of
repository paths. Each path may start with a slash ('/
') to denote an absolute path
or with a folder name to denote a path relative to a site root folder. When changing these
values, please make sure that the existing view type content items are moved or copied to the new
target location.
Web pages are represented in the CAE using the
com.coremedia.blueprint.common.contentbeans.Page
object which consists of
two elements: the content to be rendered and the context in which to render the content.
Pages where the content to be rendered is the same as the context (for example, section overview) display the page grid of the context. Pages where content items (such as Articles) are displayed within a context use display the context's page grid but replace the "main" placement with the content item.
Each placement contains a link list and several additional buttons on top of it. The order of the linked elements can be modified using drag and drop.
Instead of adding own content, a placement can inherit the linked content from a parent's page placement. If you inherit the content, you cannot edit the placement in the child page. You have to deactivate the "override" button to change the content of the placement.
A placement can be locked using the "lock" button. In this case all child placements are not able to overwrite this placement with own content.
The page grid editor provides a combo box with predefined layouts to apply to the current page. After changing the layout, the Studio preview will immediately reflect the new page layout.
The layout of a parent page grid may be changed so that it does not fit anymore with the layout of a child page which inherits some settings. A child may use a three-column layout and inherit most of its content from its parent page that also uses a three-column layout. Then, the layout of the parent may be changed to another layout with a single column that doesn't contain any of the needed layout sections. The child configuration is invalid in this case and the user has to reconfigure all child pages.
Currently there is no kind of detection for these cases in Studio, so the user has to check manually if the child configurations are still valid.
How to configure a page grid editor
The Blueprint base module bpbase-pagegrid-studio-plugin
provides an implementation
of the page grid editor shown above through the config class pageGridPropertyField
in the package com.coremedia.blueprint.base.pagegrid.config
. In many cases, you can
simply use this component in a content item form by setting only the standard configuration
attributes bindTo
, forceReadOnlyValueExpression
, and
propertyName
If you want to adapt the columns shown in the link list editors for the individual section, you
can also provide fields and columns using the attributes fields
and
columns
, respectively. The semantics of these attributes match those of the
linkListPropertyField
component.
How to configure the layout location
Pages look up layouts from global and site specific folders. By default, the site specific page
grid layout path will point to Options/Settings/Pagegrid/Layouts
and the
global one to /Settings/Options/Settings/Pagegrid/Layouts
. This can be
changed via the application property pagegrid.layout.paths
, which contains a
comma-separated list of repository paths. Each path may start with a slash ('/
') to
denote an absolute path or with a folder name to denote a path relative to a site root folder.
When changing these values, please make sure that the existing page layout content items are moved
or copied to the new target location. Also, mind that when looking for the default page layout
(see below), paths mentioned first take precedence, so it usually makes sense to start with
site-relative paths and continue with absolute paths.
Caution
The default layout settings content item PagegridNavigation
must be present
in at least one of the available layout folders. The page grid editor will show an error
message if the content item is not found.
Caution
If several layout folders are used, make sure that the layout settings content items have unique names.
How to configure a new layout
Every CMSettings
content item in a layout folder is recognized as a layout
definition. The settings
struct property defines a table layout with
different sections. The struct defines two integer properties with the overall row and column
count. The struct data may also contain two string properties name
and
description
, which are used for the localization of page grid layout
content items (see Section “How to localize page grid objects”).
The items
property contains a list of substructs, each defining a section
of the page grid. The order in which the sections appear in the struct list matches the order in
which the link lists of the individual sections are shown by the page grid editor.
The sections are represented by CMSymbol
content items. The layout definition
is inspired by the HTML table model, even though CoreMedia
Blueprint's default templates do not render page grids as HTML tables but with CSS
means. The sections support the following attributes:
col
: The column number where the section is placed or, if thecolspan
attribute is set, the column number of the leftmost part of the section.row
: The row number where the section is placed or, if therowspan
attribute is set, the row number of the topmost part of the section.colspan
: The number of columns spanned by the section.rowspan
: The number of rows spanned by the section.width
: The width of this section in percent of the total width.height
: The height of this section in percent of the total height.
The col, row
and rowspan
attributes of the section
must match the grid layout defined by the colCount
and
colRow
attributes (see Example 5.1, “Pagegrid example definition”). That is, when
colCount
and colRow
are "3" and "4", for example,
then you have 12 cells in the page grid table layout which must all be filled by the sections.
No cell can be left empty, and no section can overlap with other sections.
The height attribute is only used for the preview of the layout in the page form. It has no impact on the delivered website.
The default PagegridNavigation
layout settings content item with a 75%/25% two
column layout looks as follows:
<Struct xmlns="http://www.coremedia.com/2008/struct" xmlns:xlink="http://www.w3.org/1999/xlink"> <IntProperty Name="colCount">2</IntProperty> <IntProperty Name="rowCount">1</IntProperty> <StructListProperty Name="items"> <Struct> <LinkProperty Name="section" xlink:href="coremedia:///cap/content/550" LinkType="coremedia:///cap/contenttype/CMSymbol"/> <IntProperty Name="row">1</IntProperty> <IntProperty Name="col">1</IntProperty> <IntProperty Name="height">100</IntProperty> <IntProperty Name="width">75</IntProperty> <IntProperty Name="colspan">1</IntProperty> </Struct> <Struct> <LinkProperty Name="section" xlink:href="coremedia:///cap/content/544" LinkType="coremedia:///cap/contenttype/CMSymbol"/> <IntProperty Name="row">1</IntProperty> <IntProperty Name="col">2</IntProperty> <IntProperty Name="height">100</IntProperty> <IntProperty Name="width">25</IntProperty> <IntProperty Name="colspan">1</IntProperty> </Struct> </StructListProperty> <StringProperty Name="name">2-Column Layout (75%, 25%)</StringProperty> <StringProperty Name="description">Two column layout with main and sidebar sections</StringProperty> </Struct>
Example 5.1. Pagegrid example definition
Caution
The main content of a content item will always be rendered into the main
section of a layout. Therefore, every layout must define a main
section.
How to configure a read-only placement
The page grid layout definition provides the possibility to declare a read-only section. Such
sections are typically filled with content from third-party integrations. If unspecified, a
section is editable. In order to disable editing, you have to declare the Boolean property
editable
for the struct
element of the corresponding
section and set it to "false", for example:
<Struct> <LinkProperty Name="section" xlink:href="coremedia:///cap/content/120" LinkType="coremedia:///cap/contenttype/CMSymbol"/> <IntProperty Name="row">2</IntProperty> <IntProperty Name="col">1</IntProperty> <IntProperty Name="colspan">1</IntProperty> <IntProperty Name="height">75</IntProperty> <IntProperty Name="width">25</IntProperty> <BooleanProperty Name="editable">false</BooleanProperty> </Struct>
The section that matches the given symbol will be shown as disabled in Studio. The matching placements will not appear in the editor.
How to disable the inheritance of the placement
The page grid layout definition provides the possibility to declare a section for which the inheritance of placements
is disabled. For such section the placement will be never inherited from parent but must be provided for each children.
In order to disable the inheritance, you have to declare the Boolean property
disableInheritance
for the struct
element of the corresponding
section and set it to "true", for example:
<Struct> <LinkProperty Name="section" xlink:href="coremedia:///cap/content/120" LinkType="coremedia:///cap/contenttype/CMSymbol"/> <IntProperty Name="row">2</IntProperty> <IntProperty Name="col">1</IntProperty> <IntProperty Name="colspan">1</IntProperty> <IntProperty Name="height">75</IntProperty> <IntProperty Name="width">25</IntProperty> <BooleanProperty Name="disableInheritance">true</BooleanProperty> </Struct>
For the section that matches the given symbol the inheritance and locking in the Studio are disabled.
You can also disable the inheritance for all sections for a given layout by declaring the Boolean property
disableInheritance
to 'true' in the first level as shown in the following example:
<Struct xmlns="http://www.coremedia.com/2008/struct" xmlns:xlink="http://www.w3.org/1999/xlink"> <IntProperty Name="colCount">2</IntProperty> <IntProperty Name="rowCount">1</IntProperty> <BooleanProperty Name="disableInheritance">true</BooleanProperty> <StructListProperty Name="items"> <Struct> <LinkProperty Name="section" xlink:href="coremedia:///cap/content/550" LinkType="coremedia:///cap/contenttype/CMSymbol"/> <IntProperty Name="row">1</IntProperty> <IntProperty Name="col">1</IntProperty> <IntProperty Name="height">100</IntProperty> <IntProperty Name="width">75</IntProperty> <IntProperty Name="colspan">1</IntProperty> </Struct> <Struct> <LinkProperty Name="section" xlink:href="coremedia:///cap/content/544" LinkType="coremedia:///cap/contenttype/CMSymbol"/> <IntProperty Name="row">1</IntProperty> <IntProperty Name="col">2</IntProperty> <IntProperty Name="height">100</IntProperty> <IntProperty Name="width">25</IntProperty> <IntProperty Name="colspan">1</IntProperty> </Struct> </StructListProperty> <StringProperty Name="name">2-Column Layout (75%, 25%)</StringProperty> <StringProperty Name="description">Two column layout with main and sidebar sections</StringProperty> </Struct>
How to disable the default inheritance of the placement
For a new page grid the placement is per default inherited from a parent. You can declare a section for which the inheritance of placements
is not default. For such section the placement will be empty first before you activate the inheritance or fill the placement on your own.
In order to make the non-inheritance default, you have to declare the Boolean property
defaultInheritance
for the struct
element of the corresponding
section and set it to "false", for example:
<Struct> <LinkProperty Name="section" xlink:href="coremedia:///cap/content/120" LinkType="coremedia:///cap/contenttype/CMSymbol"/> <IntProperty Name="row">2</IntProperty> <IntProperty Name="col">1</IntProperty> <IntProperty Name="colspan">1</IntProperty> <IntProperty Name="height">75</IntProperty> <IntProperty Name="width">25</IntProperty> <BooleanProperty Name="defaultInheritance">false</BooleanProperty> </Struct>
You can also make the non-inheritance default for all sections for a given layout by declaring the Boolean property
defaultInheritance
to 'false' in the first level - similar as the disableInheritance
.
Caution
For an existing layout which is used for many page grids changing the flags disableInheritance
and defaultInheritance
will change the contents of the page grids.
Especially if the page grids are indexed by the CAE Feeder they all be re-indexed.
Use the flags with caution.
How to populate a page grid with content
Page grids are defined in the struct property CMNavigation.placement
of a
channel. Such structs are typically created using the page grid editor shown above. Example:
<Struct xmlns="http://www.coremedia.com/2008/struct" xmlns:xlink="http://www.w3.org/1999/xlink"> <StructListProperty Name="placements"> <Struct> <LinkProperty Name="section" LinkType="coremedia:///cap/contenttype/CMSymbol" xlink:href="coremedia:///cap/content/550"/> <LinkProperty Name="viewtype" LinkType="coremedia:///cap/contenttype/CMViewtype" xlink:href="coremedia:///cap/content/1784"/> <LinkListProperty Name="items" LinkType="coremedia:///cap/contenttype/CMArticle"> <Link xlink:href="coremedia:///cap/content/134"/> <Link xlink:href="coremedia:///cap/content/498"/> </LinkListProperty> </Struct> <Struct> <LinkProperty Name="section" LinkType="coremedia:///cap/contenttype/CMSymbol" xlink:href="coremedia:///cap/content/544"/> <LinkListProperty Name="items" LinkType="coremedia:///cap/contenttype/CMArticle"> <Link xlink:href="coremedia:///cap/content/776"/> </LinkListProperty> </Struct> </StructListProperty> <StructProperty Name="placements_2"> <Struct> <LinkProperty Name="layout" LinkType="coremedia:///cap/contenttype/CMLayout" xlink:href="coremedia:///cap/content/3488"/> </Struct> </StructProperty> </Struct>
A placement struct contains a list of section structs placements
. The
placements_2
struct contains another struct,
placements
and a link property layout
, which
determines the layout for this channel.
The placements
struct property consists of substructs for the single
placements, each of which refers to a section and lists its contents in the items property.
Additionally, each placement can declare a view type.
Layouts and placements are connected by the section content items. Let's assume you have two sections, "main" and "sidebar". Your channel declares some latest news for the main section and some personalized recommendations for the sidebar. The layout definition consists of one row with two columns, the left column refers to the "main" section, the right column refers to the "sidebar". This will make your channel be rendered with the main content left and the recommendations on the right. If you don't like it, you can simply choose another layout, for example with a different width ratio of the columns or with the sidebar left to the main section.
The rendering of a page grid is layout-driven, because the sections of the table-like layout model must be passed to the template in an order which is suitable for the output format (usually HTML). CoreMedia Blueprint's web application processes a page grid as follows:
The
PageGridServiceImpl
determines the layout content item of the channel. If there is no layout link in theplacements_2
struct, a fallback content itemPagegridNavigation
is used. This name can be configured by setting the application propertypagegrid.layout.defaultName
. The fallback layout content item can be located in any of the configured layout folders (see "layout locations"), usually it will be located under the site relative pathOptions/Settings/Pagegrid/Layouts
. The layout definition is evaluated and modeled by aContentBackedStyleGrid
.The
PageGridServiceImpl
collects the placements of the channel itself and the parent channel hierarchy. The precedence is obvious, for example a channel's own placement for a section ("sidebar" for instance) overrides an ancestor's placement for that section.Both layout and placements are composed in a
ContentBackedPageGrid
which is the backing data for aPageGridImpl
.PageGridImpl
implements thePageGrid
interface and prepares the data of theContentBackedPageGrid
for access by the templates. Basicallyit wraps the content of the placements into content beans,
it arranges the placements in rows and columns, according to the layout
it replaces the channel's main placement with the requested content.
Blueprint's default templates (namely
PageGrid.ftl
) do not render page grids as HTML tables but as nested
<div> elements and suitable CSS styles. The beginning of a rendered page grid looks like
this:
<div id="row1" class="row"> <div id="main" class="col1 column col1of2 width67">
The outer <div> elements represent the rows of the page grid, the inner <div> elements represent the columns. The ids of the rows are generated by the template as an enumeration. The ids of the columns are the section names of the placements. The column <div> elements are rendered with several class attributes:
column
: A general attribute for column <div> elementscol1
: The absolute index of the column in its rowcol1of2
: Thecolspan
of this column (1) and the absolute number of columns of the page grid (2)width67
: The relative width of this column
You can use these attributes to define appropriate styles for the columns.
CoreMedia Blueprint's default CSS provides styles which reflect the
width ratios of some typical multi-column layouts. You find them in the content item
/Themes/basic/css/basic.css
in the content repository where you can enhance
or adapt them to your needs.
In the inner <div> elements the placements are included, and their section names
determine the views. For example a "sidebar" placement is included by the
PageGridPlacement.sidebar.jsp
template.
How to localize page grid objects
To localize a layout name, create a resource bundle entry with the key
<layoutname>_text
in the resource bundle
PageGridLayouts_properties
, where <layoutname>
is the name
of the layout content item or, preferably, the name
property of the settings struct of
the layout. Similarly, a layout description can be localized with entries of the form
<layoutname>_description
. If no corresponding resource bundle entries are
found, the description
property of the settings struct of the layout is used. If
that property is empty, too, the name is used as the description. The resource bundle is
available in the package com.coremedia.blueprint.base.pagegrid
of module
bpbase-pagegrid-studio-plugin
.
For the purposes of localization, placements are treated as pseudo-properties and localized
according to the standard rules for content properties as described in the
Studio Developer Manual. The name of the pseudo-property is
<structname>-<placementname>
, where
<structname>
is the name of the struct property storing the page grid and
<placementname>
is the name of the section content item. For example, a
placement with the name main
that is referred from the standard page grid struct
placement
of a CMChannel
content item would obtain its localization using
the key CMChannel_placement-main_text
. You can add localization entries to the
resource bundle BlueprintDocumentTypes_properties
of module
blueprint-forms
, which is applied to the built-in resource bundle
ContentTypes_properties
at runtime.
To localize a view type name or a view description, you can add a property
<viewtypename>_text
or <viewtypename>_description
to the bundle Viewtypes_properties
. Here <viewtypename>
is
the name of the view type content item or, preferably, the string stored in its layout
property. Because view types are also used in other contexts, this bundle has been placed in the
package com.coremedia.blueprint.base.components.viewtypes
of module
bpbase-studio-components
.
CoreMedia Blueprint defines three resource bundles
BlueprintPageGridLayouts_properties
, BlueprintPlacements_properties
,
and BlueprintViewtypes_properties
. Entries of these bundles are copied to the
bundles described above, providing a convenient way to add custom entries.