tag:help-archives.hannonhill.com,2010-02-09:/discussions/how-do-i/280-change-div-class-in-template-based-on-metadata-selectionCascade CMS: Discussion 2018-10-18T20:36:08Ztag:help-archives.hannonhill.com,2010-02-09:Comment/43258502010-12-17T16:17:12Z2010-12-17T16:17:12ZChange div class in template based on metadata selection<div><p>I'm trying to change the class attribute on a div located in a
Template depending on a metadata value set by the user. I cannot
simply use a current page index block and format for this because
this div is a sort of container div which contains the majority of
html (including multiple other system-regions) on the template.
I've been looking closely at this topic: <a href=
"http://help.hannonhill.com/discussions/how-do-i/19-system-tag-as-html-body-attribute">
http://help.hannonhill.com/discussions/how-do-i/19-system-tag-as-ht...</a>
and it seems to solve my problem however I'm using strictly
Velocity and I guess I don't understand XSLT enough to get this to
work.</p>
<p>In the linked to topic, a class attribute is added to the body
tag by using this line: match="node()[name()='body']". How can I
convert that to instead match a div with a specific ID? I've tried
obvious combinations like //div[@id='foo'] without success. Does
the initial match="/*" have anything to do with it? Is there a
Velocity or easier way to do this?</p></div>vrupperttag:help-archives.hannonhill.com,2010-02-09:Comment/43258502010-12-20T15:47:15Z2010-12-20T15:47:17ZChange div class in template based on metadata selection<div><p>Currently there is no way to apply a Velocity Format to an
entire Template. The best way for you to achieve this would
probably be to do what the other topic you're referencing is
doing.</p>
<p>The XSLT listed in the other topic is a good start and with a
little modification, you could apply it to a Configuration Set for
your Page.</p>
<p>I have made the necessary modifications to the XSLT format that
I think should solve your issue.</p>
<pre>
<code><?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- We get the value of the dynamic metadata field and assign it to a variable. -->
<xsl:variable name="metedataValue" select="//calling-page/system-page/dynamic-metadata[name='YOUR-FIELD-NAME']/value"/>
<xsl:template match="/*">
<xsl:copy>
<xsl:apply-templates/>
<xsl:copy-of select="@*"/>
</xsl:copy>
</xsl:template>
<!-- Here we match the XHTML div node wherethe ID attribute equals what you're looking for. -->
<xsl:template match="node()[name()='div'][@id='YOUR-DIV-ID']">
<xsl:choose>
<!-- If the value of the metadata field equals your first option,
set the class to something. -->
<xsl:when test="$metedataValue = 'YOUR-OPTION-ONE'">
<xsl:variable name="classToSet" select="YOUR-VALUE-ONE"/>
</xsl:when>
<!-- If the value of the metadata field equals your second option,
set the class to something else. -->
<xsl:when test="$metedataValue = 'YOUR-OPTION-TWO'">
<xsl:variable name="classToSet" select="YOUR-VALUE-TWO"/>
</xsl:when>
</xsl:choose>
<xsl:copy>
<!-- This is where we assign the class variable to the div node we found earlier. -->
<xsl:attribute name="class"><xsl:value-of select="$classToSet"/></xsl:attribute>
<xsl:copy-of select="@*"/>
<xsl:copy-of select="./node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet></code>
</pre>
<p>Now you only need to insert the appropriate values for what
output you desire and apply the format to a Configuration Set.</p>
<p>YOUR-FIELD-NAME is the name of the dynamic metadata field that
you are interested in.<br>
YOUR-DIV-ID is the id of the XHTML div that you are interested in
changing the class of. If this div does not currently have an id,
it will make no difference for you to add one as long as you do not
use an id that has any CSS associated with it. You could easily
make the id="myMetadataTest" and be done.</p>
<p>It sounds like you would like to set a class name based on the
metadata values and not directly use the metadata value as the
class name.<br>
YOUR-OPTION-ONE is one possible option for the metadata value.<br>
YOUR-VALUE-ONE is the corresponding class name you would like to
set for OPTION-ONE.</p>
<p>YOUR-OPTION-TWO is a second possible option for the metadata
value.<br>
YOUR-VALUE-TWO is the corresponding class name you would like to
set for OPTION-TWO.</p>
<p>You can safely repeat that block of XSLT code if you require
more that two options as well.</p>
<p>I hope this helps get you going further.</p></div>Charlie Holdertag:help-archives.hannonhill.com,2010-02-09:Comment/43258502010-12-20T16:48:13Z2010-12-20T16:48:13ZChange div class in template based on metadata selection<div><p>I can't seem to match the div using either of your examples.
Even simplifying it using strings instead of variables isn't
changing anything on page preview.</p>
<pre>
<code><?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/*">
<xsl:copy>
<xsl:apply-templates/>
<xsl:copy-of select="@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="node()[name()='div'][@id='mainspace_2']">
<xsl:copy>
<xsl:attribute name="class">TEST</xsl:attribute>
<xsl:copy-of select="@*"/>
<xsl:copy-of select="./node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet></code>
</pre>
<p>I have however had success changing the div I want by doing
this:</p>
<pre>
<code><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="*">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="@*">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="@id[.='mainspace_2']">
<xsl:attribute name="id">mainspace_2</xsl:attribute>
<xsl:attribute name="class">TEST</xsl:attribute>
</xsl:template>
</xsl:stylesheet></code>
</pre>
<p>The only problem that still remains is I can't seem to get the
dynamic metadata value. Charle in your example you access
//calling-page, which I didn't know existed on a configuration set.
Is there a way to see what XML does exist on a configuration
set?</p></div>vrupperttag:help-archives.hannonhill.com,2010-02-09:Comment/43258502010-12-20T17:37:29Z2010-12-20T17:37:29ZChange div class in template based on metadata selection<div><p>Sorry for the bad XSLT before. That code wouldn't match the
templates properly to find the div inside the HTML. The previous
code block only searched and matched for direct children elements,
so it would have done a bad job of finding a div that was nested
inside multiple other elements.</p>
<p>I spent some time testing this code with another member of the
Services team and we've come up with another version:<br></p>
<pre>
<code><?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- We get the value of the dynamic metadata field and assign it to a variable. -->
<xsl:variable name="metedataValue" select="//calling-page/system-page/dynamic-metadata[name='YOUR-FIELD-NAME']/value"/>
<xsl:choose>
<!-- If value equals first option, set class to something. -->
<xsl:when test="$metedataValue = 'YOUR-OPTION-ONE'">
<xsl:variable name="classToSet" select="YOUR-VALUE-ONE"/>
</xsl:when>
<!-- If value equals second option, set class to something else. -->
<xsl:when test="$metedataValue = 'YOUR-OPTION-TWO'">
<xsl:variable name="classToSet" select="YOUR-VALUE-TWO"/>
</xsl:when>
</xsl:choose>
<xsl:template match="/*">
<xsl:copy>
<xsl:apply-templates/>
<xsl:copy-of select="@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="node()">
<xsl:copy>
<xsl:if test="name()='div' and @id='mainspace_2'">
<xsl:attribute name="class"><xsl:value-of select="$classToSet"/></xsl:attribute>
</xsl:if>
<xsl:copy-of select="@*"/>
<!-- Recursively loop through nodes until we find the correct div. -->
<xsl:apply-templates select="./node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet></code>
</pre></div>Charlie Holdertag:help-archives.hannonhill.com,2010-02-09:Comment/43258502010-12-20T19:33:48Z2010-12-20T19:33:48ZChange div class in template based on metadata selection<div><p>That seemed to work after switching the <xsl:if and
<xsl:copy-of lines inside the xsl:template match="node()" area.
Also, the xsl:choose block threw an error for being in an invalid
area. Working code:</p>
<pre>
<code><?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/*">
<xsl:copy>
<xsl:apply-templates/>
<xsl:copy-of select="@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="node()">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:if test="name()='div' and @id='mainspace_2'">
<xsl:attribute name="class">TEST</xsl:attribute>
</xsl:if>
<xsl:apply-templates select="./node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet></code>
</pre>
<p>But I still can not access dynamic metadata. Is this possible
from an XSLT format attached to a configuration set and not an
index block?</p></div>vrupperttag:help-archives.hannonhill.com,2010-02-09:Comment/43258502010-12-20T20:06:41Z2010-12-20T20:07:58ZChange div class in template based on metadata selection<div><p>Hmmm. I guess the XSLT is running on the final HTML that is
being generated from all of the blocks and formats.</p>
<p>Using a current page block and another <system-region>
tag, you could place a div after the body tag of your HTML that
only contains the name of the class you want to set after you run
your logic.<br></p>
<pre>
<code><div id="hiddenVal" style="display:none;">className</div></code>
</pre>
<p>And then instead of the if logic in the XSLT, just pull that
value and add it.<br></p>
<pre>
<code><xsl:variable name="classToSet" select=".//node()[name() = 'div'][@id = 'hiddenVal']"/></code>
</pre></div>Charlie Holdertag:help-archives.hannonhill.com,2010-02-09:Comment/43258502010-12-21T21:07:49Z2010-12-21T21:07:49ZChange div class in template based on metadata selection<div><p>That is definitely a solution but I think overall this process
is going to get messier and messier. Ultimately I've found a way to
avoid having the class name be necessary at all. Thank you for your
help, I now know more about how Cascade works and how XSLT formats
can be applied to config sets and templates.</p></div>vruppert