Turbo twitter Bootstrap theming for Plone using Diazo¶
When building a new Plone theme based on twitter Bootstrap without modifying core templates you have to do a lot of xsl-styling. Hopefully this article can help you getting started.
Building a diazo theme¶
You should have basic knowledge of how to build a diazo
theme in
Plone. So you will have a file called
rules.xml
and hopefully your
bootstrap javascript and css
code already plugged into Plone resource registries. An installable
Plone product is available
here.
Read more about bootstrap css-classes and javascript components.
Content Views¶
Transforming the edit-bar is not very hard, following rule provides a really good working solution.
Mark active tab in content views¶
<xsl:template match="//ul//@class[contains(., 'selected')]">
<xsl:attribute name="class">
<xsl:value-of select="." /> active
</xsl:attribute>
</xsl:template>
<xsl:template match="//ul//@class[contains(., 'contentActions')]">
<xsl:attribute name="class">nav nav-tabs</xsl:attribute>
</xsl:template>
Form Buttons¶
I’ve decided to use btn-danger
for all remove and delete buttons and
btn-primary
for primary submit buttons.
<xsl:template match="//input[@type[contains(., 'submit') or contains(., 'button')]]">
<input>
<xsl:copy-of select="attribute::*[not(name()='class')]" />
<xsl:attribute name="class"><xsl:value-of select="@class" /> btn
<xsl:if test="@name[contains(., 'delete') or contains(., 'Remove')]">btn-danger</xsl:if>
<xsl:if test="@name[contains(., 'save') or contains(., 'Save') or contains(., 'RenameAll')]">btn-primary</xsl:if>
</xsl:attribute>
</input>
</xsl:template>
Tables¶
By applying additional classes, you’ll get nice bootstrap tables.
<xsl:template match="//table[@class[contains(., 'listing')]]">
<table>
<xsl:copy-of select="attribute::*[not(name()='class')]" />
<xsl:attribute name="class">table-striped table-bordered table-hover table <xsl:value-of select="@class" /></xsl:attribute>
<xsl:apply-templates />
</table>
</xsl:template>
ListingBar
listingBar
was tricky to transform, of course it would be easier to
just customize the listingBar
viewlet, but if you don’t want to
touch Plone’s templates, you can use the xsl-transformations below.
<xsl:template match="//div[@class='listingBar']">
<div>
<xsl:copy-of select="attribute::*[not(name()='class')]" />
<xsl:attribute name="class"><xsl:value-of select="@class" /> pagination</xsl:attribute>
<ul>
<xsl:if test="span[@class='previous']/a">
<li>
<xsl:copy-of select="span[@class='previous']/a" />
</li>
</xsl:if>
<xsl:for-each select="*[not(contains(@class, 'previous')) and not(contains(@class, 'next'))]">
<xsl:choose>
<xsl:when test="child::a and not(child::text())">
<li>
<xsl:copy-of select="./a[text()]" />
</li>
</xsl:when>
<xsl:when test="child::a and child::text()">
<xsl:if test="position() = last()">
<li>
<xsl:attribute name="class">disabled</xsl:attribute>
<a>
<xsl:attribute name="href">#</xsl:attribute>
<xsl:copy-of select="text()" />
</a>
</li>
</xsl:if>
<li>
<xsl:copy-of select="./a[text()]" />
</li>
<xsl:if test="position() = 1">
<li>
<xsl:attribute name="class">disabled</xsl:attribute>
<a>
<xsl:attribute name="href">#</xsl:attribute>
<xsl:copy-of select="text()" />
</a>
</li>
</xsl:if>
</xsl:when>
<xsl:when test="name()='span' and not(child::a)">
<li>
<xsl:attribute name="class">active</xsl:attribute>
<a>
<xsl:attribute name="href">#</xsl:attribute>
<xsl:copy-of select="text()" />
</a>
</li>
</xsl:when>
<xsl:when test="@href">
<li>
<a>
<xsl:attribute name="href"><xsl:value-of select="@href" /></xsl:attribute>
<xsl:copy-of select="text()" />
</a>
</li>
</xsl:when>
<xsl:otherwise>
<li>
<xsl:attribute name="class">disabled</xsl:attribute>
<a>
<xsl:attribute name="href">#</xsl:attribute>
<xsl:copy-of select="text()" />
</a>
</li>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<xsl:if test="span[@class='next']/a">
<li>
<xsl:copy-of select="span[@class='next']/a" />
</li>
</xsl:if>
</ul>
</div>
</xsl:template>