Thursday, November 3, 2011

Common Diazo Rules for Plone

Here is a list of rules that I have used in various situations when preparing a Diazo theme for Plone.
If something is written in red below it represents a placeholder, you will need to replace the example placeholder with one that is appropriate for your rules.xml file. If something is written in green it is a variable, this too can be changed as you see fit. Everything else should work as is.

Insert the homepage link into an element of your choice

This rule will grab the link to the home page from your plone content and associate it with an element in your theme.
<copy attributes="href" css:theme=".logo a" css:content="#portal-logo" />

Adding the main plone content to a specific container.

This is the fastest way to get 'guts' of a Plone site into a container provided by your theme. The example below inserts the site content into a container with the id 'mycontainer'. The drawback of this method is that the portlets (sidebars) do not inherit the theme style. This is useful if you want to preserve the edit bar and other functionality for logged in users.
<replace css:theme-children="#mycontainer" css:content="#portal-columns"/>

Ensure that the body tag inherits Plone classes.

Plone injects several classes to the body tag, these are used to distinguish one page from another.
<!-- BODY THEME (inject body classes from Plone into the theme) --> <copy attributes="*" css:theme="body" css:content="body" />

Replace the theme title and base tags in the head.

These rule "pull" stylesheets from the Plone site into the head of the themed site.
<!-- Base tag --> <replace theme="/html/head/base" content="/html/head/base" /> 
<!-- HEAD: title -->  <replace theme="/html/head/title" content="/html/head/title" /> <before theme="/html/head" content="/html/head" />

Prevent the theme from affecting pages that are not Plone.

Areas such as the Zope Management Interface (ZMI) and most popups should not be themed, the following 'rule' ensures that we only enable the theme when there is a #visual-portal-wrapper present in the markup:
<theme href="index.html" css:if-content="#visual-portal-wrapper"/>
the is a variation of the same rule:
<rules css:if-content="#visual-portal-wrapper"> <theme href="index.html" css:if-content="#visual-portal-wrapper"/> </rules>

Add Login and Personal Tools.

The example below assumes that there is an id which surrounds the theme called 'mainwrapper'
<!-- ADD LOGIN/Personal Tools --> 
<before css:theme='#mainwrapper' css:content='#portal-personaltools-wrapper' />

Ensure that tinymce popups remain unstyled

<notheme if-path="presentation_view"/> <notheme if-path="source_editor.htm"/> <notheme if-path="ploneimage.htm"/> <notheme if-path="anchor.htm"/> <notheme if-path="table.htm"/> <notheme if-path="attributes.htm"/>

Add Edit bar to content

Edit Bar provides the green content bar. Prevent unwanted styling to the edit bar by adding the #edit-bar before the content of your theme. If the main content area is #contentBlock then something like this:
<before css:content="#edit-bar" css:theme="#contentBlock"/>

Use method="raw" to force a rule to work even after the selector has been dropped by another rule.

In the example below the viewlet has been dropped from the content by the first rule but it is still possible to add it back to the theme using a replace rule with the method="raw", the replace acts upon an id called 'top-viewlet-holder'.
<drop css:content="#viewlet-above-content"/>

<replace method="raw" css:theme="#top-viewlet-holder" css:content="#viewlet-above-content"/>

Append the <script> tag at the bottom of your theme.

This example places the scripts after all other elements in the body, this is important to ensure that analytics or other javascript based includes show up in the theme.
<after css:content='#visual-portal-wrapper script' css:theme-children='body'/>

Conditionally load a different theme template

In this example we have two html templates, the 'theme-full' template is called if .... otherwise it will default to the the 'theme.html' template.
<theme href="theme-postgrad.html" css:if-content="#portal-column-content.width-full" />
<theme href="theme.html" />

Dynamically merge class from theme with class from content

In this example we merge the classes provided by both the theme and the content but only if he content has a class called 'section-carousel'.
<merge attributes="class" css:theme="body" css:content="body" css:if-content='.section-carousel'/>

Use XSL with Diazo

If you need more logic try setting and using variables (requires use of XSL)
<xsl:variable name="carousel" css:select="body .carouselWrapper"/> <rules if-content="not($carousel)"> <drop css:theme="#header" /> </rules>

Other resources:

A few other Diazo examples and how to use a manifest.cfg file -
For more advanced usage visit:


Pieter B. Ruiter said...
This comment has been removed by the author.
Pieter B. Ruiter said...

Might this example have the two items backwards?

Append the script tag at the bottom of your theme.
This example places the scripts after all other elements in the body, this is important to ensure that analytics or other javascript based includes show up in the theme.

after css:content='#visual-portal-wrapper script' css:theme-children='body'

I would expect:

after css:theme-children='body' css:content='#visual-portal-wrapper script'

Perhaps I'm misreading it?

David B said...

When working with the after and before directives, node(s) matched in the content are ALWAYS inserted into the node(s) matched in the theme. So content always "travels" from the content to the theme, never the other direction. The order doesn't matter, but I can see how your suggestion would be more readable.

Sign up for my upcoming Plone 5 Book & Video tutorials

plone 5 for newbies book and videos