in pursuit of the grand unified template
DESCRIPTION
#CSUC14TRANSCRIPT
In Pursuit of the Grand Unified Templateor
Page Level Formats
Jason AllerUC Davis School of Law#csuc14, @JasonAller
Who am I?
• Cascade Server Admin and Developer• This is my seventh Users Conference• I make things like:– The Cascade Entity Relationship Diagram– grunt-cascade-deploy on github– soap-cascade on github
A thanks to the folks at Tarleton
As the manager of www.tarleton.edu, Web Services reserves the right to edit any Tarleton webpage at any time in order to make corrections and improvements to items such as misspellings, poor content structure, accessibility issues, copyright issues, security issues, and outdated information. Web Services may not contact the content owner in advance but will make an effort to communicate the changes and issues soon after they are made.
Overview
I’m going to be using XSLT for my examples, though I did buy “Velocity: The Basics” by James Johnson• Changing Links• Conditional Restructuring - Bootstrap• Exposing additional data at the page level
Conditional Restructuring
• Bootstrap – but can be used with many other CSS frameworks
• One design with multiple layouts• From a single template• Let the system do all the work automatically• Because automating the CMS is more effective
than training content contributors
The page as XML source
XSLT Default Templates
• Traverse Elements<xsl:template match="*|/">
<xsl:apply-templates/></xsl:template>
• Process content and attributes<xsl:template match="text()|@*">
<xsl:value-of select="."/></xsl:template>
• Remove comments and processing instructions<xsl:template match="processing-instruction()|comment()"/>
Changing Links
• Find with XPath– <a…– <a href="http…– <a href="mailto:…
• Process the element (copy, modify, remove)• Unless removing, send that element’s content
to be processed – recurse
Changing Links
• Add Google Tracking to outgoing links• Append a non-breaking space and an icon
after the link for links to PDF and PowerPoint files
Link code<xsl:template match="node()[name() = 'a']"> <!-- begin copying the source node --> <xsl:copy> <!-- If we might want to track this with Google: --> <xsl:if test="starts-with(@href,'http')"> <xsl:choose> <!-- Check if there is already an onClick event and add ours --> <xsl:when test="@onClick"> <xsl:attribute name="onClick"> <xsl:value-of select="concat(@onClick,' ')"/> <xsl:call-template name="pageTracker"/> </xsl:attribute> </xsl:when> <!-- of if there wasn't an onClick event add one --> <xsl:otherwise> <xsl:attribute name="onClick"> <xsl:call-template name="pageTracker"/> </xsl:attribute> </xsl:otherwise> </xsl:choose> </xsl:if>
Link code cont. <!-- process non-onClick attributes and child nodes --> <xsl:apply-templates select="@*[name() != 'onClick']|node()"/> <!-- figure out if we need to add docIcons --> <xsl:choose> <xsl:when test="child::node()[name() = 'img']"> <!-- Do nothing, because link is wrapped around graphic --> </xsl:when> <xsl:when test="substring(@href,string-length(@href)-3,4) = '.pdf'"> <xsl:text> </xsl:text> <span class="sprite pdf-n"></span> </xsl:when> <xsl:when test="substring(@href,string-length(@href)-3,4) = '.ppt' or substring(@href,string-length(@href)-4,5) = '.pptx'"> <xsl:text> </xsl:text> <span class="sprite ppt-n"></span> </xsl:when> <xsl:otherwise/> </xsl:choose> </xsl:copy></xsl:template>
pageTracker<xsl:template name="pageTracker"> <xsl:text>javascript:pageTracker.</xsl:text> <xsl:text>_trackPageview('</xsl:text> <xsl:value-of select="$pagePath"/> <xsl:text>/outgoing/</xsl:text> <xsl:value-of select="translate(., $singleQuote, '')"/> <xsl:text>/</xsl:text> <xsl:value-of select="substring-after (@href,'http://')"/> <xsl:text>');</xsl:text></xsl:template>/current/portal/outgoing/Intranet/intranet.law.ucdavis.edu/index.aspx
Conditional Restructuring
• Determine rules– Decide the logic once, then apply it
• Output alternative wrapper elements• Process content – recurse• It’s turtles all the way down
navmidbar(2)
2 8 2
navmidbar(3)
2 7 3
navmid
2 10
midbar(2)
10 2
midbar(3)
9 3
mid
12
home
4 5 3
Phone
home
4 5 3
navmidbar(3)
2 7 3
navmid
2 10
mid
12
midbar(2)
10 2
Bootstrap
Bootstrap is based on 12 columns and wants<div class="col-sm-3">or<div class="col-sm-2">We want to have a single template to maintain that can allow three columns with the following options:• Left – either 2 or 0• Main – either 7, 8, 9, 10, or 12 – fills space• Right – either 0, 2, or 3
One Template<div id="zeroth">
<div class="row"><div id="first">
<system-region name="SUBNAV"/><system-region name="QUICKLINKS"/>
</div><div id="second">
<system-region name="CONTENT-TITLE"/><system-region name="DEFAULT-PRE"/><system-region name="DEFAULT"/><system-region name="DEFAULT-POST"/>
</div><div id="third">
<system-region name="SIDEBAR-TOP"/><system-region name=“SIDEBAR"/>
<system-region name="SIDEBAR-BOTTOM"/></div>
</div></div>
Pseudocode Tour
• Check for content in each area• Pick a layout based on this• For each area apply the rules of that layout– zeroth– first– second– third
Checking for <div> Content
<xsl:variable name="con1"select="count(
//node()[name()='div'][@id='first']
/*[not(name() = 'img' andsubstring(@src,1,10) = '/css/icons')])"/>
Layout Assignment Logic
<xsl:variable name="layout"> <xsl:choose> <xsl:when test="$pagePath = '/index'"> <xsl:text>home</xsl:text> </xsl:when> <xsl:when test="$con1 = 0 and not($con2 = 0) and $con3 = 0"> <xsl:text>mid</xsl:text> </xsl:when>
home
4 5 3
mid
12
Layout cont.<xsl:when test="not($con1 = 0) and not($con2 = 0) and $con3 = 0"> <xsl:text>navmid</xsl:text></xsl:when><xsl:when test="not($con1 = 0) and not($con2 = 0) and not($con3 = 0)"> <xsl:text>navmidbar</xsl:text></xsl:when><xsl:when test="$con1 = 0 and not($con2 = 0) and not($con3 = 0)"> <xsl:text>midbar</xsl:text></xsl:when>
navmidbar(2)
2 8 2
navmid
2 10
midbar(2)
10 2
Layout cont.
<xsl:otherwise> <xsl:text>default</xsl:text> </xsl:otherwise> </xsl:choose></xsl:variable>
zeroth<xsl:template match="node()[name()='div'][@id='zeroth']"> <xsl:choose> <xsl:when test="$layout = 'home'"> <div class="container" id="content"> <xsl:apply-templates select="node()"/> </div> </xsl:when> <xsl:otherwise> <div class="container"> <xsl:apply-templates select="node()"/> </div> </xsl:otherwise> </xsl:choose></xsl:template>
first
<xsl:template match="node() [name()='div'][@id='first']"> <xsl:choose> <xsl:when test="$layout = 'home'"> <div class="col-md-3 col-md-push-9"> <xsl:apply-templates /> </div> </xsl:when>
home
4 5 3
first cont.<xsl:when test="$layout = 'navmid'
or $layout = 'navmidbar'"><div class="col-sm-2">
<xsl:if test="./div[@id = 'subNav'] or ./div[@id = 'relatedLinks'] or ./div[@class = 'left-column-full-width']">
<xsl:attribute name="class"><xsl:text>col-sm-2
left-column</xsl:text></xsl:attribute>
</xsl:if><xsl:apply-templates />
</div></xsl:when>
navmidbar(2)
2 8 2
first cont.
<xsl:otherwise/> </xsl:choose></xsl:template>
midbar(2)
10 2
midbar(3)
9 3
mid
12
second<xsl:template match="node()
[name()='div'][@id='second']"> <xsl:choose> <xsl:when test="$layout = 'home'"> <div class="col-md-4 col-md-pull-3"> <xsl:apply-templates select="node()"/> </div> </xsl:when> <xsl:when test="$layout = 'mid'"> <div class="col-sm-12" id="content"> <xsl:apply-templates select="node()"/> </div> </xsl:when>
mid
12
home
4 5 3
second cont. <xsl:when test="$layout = 'navmid'"> <div class="col-sm-10" id="content"> <xsl:apply-templates select="node()"/> </div> </xsl:when> <xsl:when test="$layout = 'midbar'"> <div id="content"> <xsl:attribute name="class"> <xsl:choose> <xsl:when test="$sidebar = '3'"> <xsl:text>col-sm-9</xsl:text> </xsl:when> <xsl:otherwise> <xsl:text>col-sm-10</xsl:text> </xsl:otherwise> </xsl:choose> </xsl:attribute> <xsl:apply-templates select="node()"/> </div> </xsl:when>
navmid
2 10
midbar(2)
10 2
midbar(3)
9 3
second cont. <xsl:otherwise> <div id="content"> <xsl:attribute name="class"> <xsl:choose> <xsl:when test="$sidebar = '3'"> <xsl:text>col-sm-7</xsl:text> </xsl:when> <xsl:otherwise> <xsl:text>col-sm-8</xsl:text> </xsl:otherwise> </xsl:choose> </xsl:attribute> <xsl:apply-templates /> </div> </xsl:otherwise> </xsl:choose></xsl:template>
navmidbar(2)
2 8 2
navmidbar(3)
2 7 3
third
<xsl:template match="node()[name()='div'][@id='third']">
<xsl:choose> <xsl:when test="$layout = 'home'"> <div class="col-md-5 col-md-pull-3"> <xsl:apply-templates /> </div> </xsl:when>
home
4 5 3
third cont.<xsl:when test="$layout = 'navmidbar' or $layout = 'midbar'"> <div id="right-column"> <xsl:attribute name="class"> <xsl:choose> <xsl:when test="$sidebar = '3'"> <xsl:text>col-sm-3</xsl:text> </xsl:when> <xsl:otherwise> <xsl:text>col-sm-2</xsl:text> </xsl:otherwise> </xsl:choose> </xsl:attribute> <xsl:apply-templates /> </div></xsl:when>
midbar(2)
10 2
midbar(3)
9 3
third cont.
<xsl:otherwise/> </xsl:choose></xsl:template>
Exposing metadata at the page level
• Expose at template level• Extract values to variables• Add rule to remove – swallow it with the
format
Insert
• <system-region name="CASCADE-METADATA"/>
• Index block self-metadata• <xsl:template match="/">
<xsl:copy-of select="/"/></xsl:template>
Extract
Pull the page path out:• <xsl:variable name="pagePath" select="//calling-page/system-page/path"/>
Pull page metadata:• <xsl:variable name="sidebar" select="//calling-page/system-page/dynamic-metadata[name = 'sidebar']/value"/>
Swallow the data to prevent publishing it:• <xsl:template match="node()[name() = 'system-index-block']"/>
Future plans
• RFC3966 tel: URI• Not <blockquote> from <p> with “”– I’ll write my own replacement for TinyMCE before
I do that! With Cascade 8 I won’t have to!• Use [system-view:internal] and [system-
view:external] to highlight violations of the style guide
• Take a vacation