Content area that only displays if there is content entered in the block

voltmer1's Avatar

voltmer1

24 Apr, 2015 04:18 PM

I have some templates that have multiple content areas that could potentially have something entered into them as needed, but I have styles on these area and don't want some empty colored box displaying if there is no content within the block. How would I make this area only display if it were being used?

  1. 1 Posted by Ryan Griffith on 24 Apr, 2015 06:27 PM

    Ryan Griffith's Avatar

    Hi,

    Your best bet would be to check if these areas have content prior to outputting those wrapping containers. If these are WYSIWYG fields, feel free to check out this page for example code you can use to check if a WYSIWYG is empty or not.

    Please let me know if you have any questions.

    Thanks!

  2. 2 Posted by voltmer1 on 27 Apr, 2015 02:49 PM

    voltmer1's Avatar

    Thanks Ryan, but on the xslt example why do you need the <xsl:copy-of> statement after the test?

  3. 3 Posted by Ryan Griffith on 27 Apr, 2015 03:31 PM

    Ryan Griffith's Avatar

    Hi,

    The <xsl:copy-of> statement is the part that outputs the WYSIWYG contents.

    This is tag is used as opposed to <xsl:value-of> to properly output both HTML tags and plain text content that can be present within the WYSIWYG field.

    Please let me know if you have any questions.

    Thanks!

  4. 4 Posted by voltmer1 on 27 Apr, 2015 03:33 PM

    voltmer1's Avatar

    I also tried the velocity version, but it doesn't display the contance of the area with the wysiwyg field after passing the "if" statement.
    It only displays the string "$_SerializerTool.serialize($wysiwygField, true))".
    Here is the full velocity code I am using:

    #set ($wysiwygField = $_XPathTool.selectSingleNode($contentRoot, "//wysiwyg-field"))
    #if ($wysiwygField.value != "" or $wysiwygField.getChildren.size() > 0 )
    $_SerializerTool.serialize($wysiwygField, true))
    #end

  5. 5 Posted by voltmer1 on 27 Apr, 2015 07:23 PM

    voltmer1's Avatar

    I've tried the XSLT version, but it's not working either. Here is my format xslt:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
        <xsl:template match="/">
            <xsl:if test="wysiwygField/node()">
                <xsl:copy-of select="wysiwygField/node()"/>
            </xsl:if>
        </xsl:template>
    </xsl:stylesheet>

    I don't understand why you would use "wysiwygField/node()"? Is "wysiwygField" a node name?

  6. 6 Posted by Ryan Griffith on 27 Apr, 2015 07:44 PM

    Ryan Griffith's Avatar

    Hi,

    You are correct, wysiwygField is just the name of the field that we used for the example. You will want to update both the XPath and field identifier within the sample code to match your particular setup.

    Please let me know if you have any questions.

    Thanks!

  7. 7 Posted by voltmer1 on 27 Apr, 2015 07:55 PM

    voltmer1's Avatar

    Still having issues:
    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
        <xsl:template match="/">
            <xsl:if test="node()/right-col">
                <xsl:copy-of select="node()/right-col"/>
            </xsl:if>
        </xsl:template>
    </xsl:stylesheet>

  8. 8 Posted by Ryan Griffith on 27 Apr, 2015 08:06 PM

    Ryan Griffith's Avatar

    Hi,

    Looking at your code, the issue is most likely due to your XPath. When you have a moment, please attach or paste the XML from your page's Data Definition and indicate what field you are trying to check and I would be happy to help out.

    Please let me know if you have any questions.

    Thanks!

  9. 9 Posted by voltmer1 on 28 Apr, 2015 02:50 PM

    voltmer1's Avatar

    Ryan,
    I guess I don’t understand the relationships between the content areas set up in the template and the data definitions within configuration sets. How to reference the different fields set up in blocks & definitions.

    My content area with the wysiwyg field with a system name of “right-col” is part of a data definition for “Landing Page”, it has an xhtml block named right-col with a format that tests for the wysiwyg field “right-col”.
    Here is my data definition for the Landing Page:

    <system-data-structure>
        <text wysiwyg="true" identifier="body-content" label="Body Content"/>
        <text type="radiobutton" identifier="display-right-col" label="Display Right-Col" default="No">
            <radio-item value="Yes" show-fields="right-col"/>
            <radio-item value="No" show-fields="right-col"/>
        </text>
        <text wysiwyg="true" identifier="right-col" label="Right-Col"/>
    </system-data-structure>

    I am also confused, if I have a wysiwyg in my data definition, do I also need to create a block for it?

  10. 10 Posted by Ryan Griffith on 28 Apr, 2015 03:19 PM

    Ryan Griffith's Avatar

    Hi Steve,

    Not a problem at all, thank you for following up.

    To summarize, pages are given a Content Type, which ties together what Configuration Set and Data Definition to use. The Configuration Set defines different outputs for the page based on file extension, template, and region assignments. The Data Definition is what provides a means of entering content/data for the page, which is then used within the various regions in your Configuration Set by way of Index Blocks and Formats. Generally, if you need to access the data for the calling page, you would either use a Velocity Format's $currentPage variable and Cascade API, or attach a calling page Index Block to the region so you have access the calling page's XML within either a Velocity Format (using the XPath Tool) or an XSLT Format.

    In this case, your page is using the data definition you provided and you most likely have two regions within your template; let's call them DEFAULT and RIGHT_COL.

    Your DEFAULT region would have a format that outputs the content entered into the body-content WYSIWYG field. This particular region is special in that the DEFAULT region does not require a calling page index block, the XML is automatically loaded into context for you. Assuming you are using Velocity, you should be able to use the following code:

    #set ( $bodyContent = $currentPage.getStructuredDataNode("body-content") )
    $bodyContent.textValue
    

    Or, if you would like to use the XPath Tool:

    #set ( $bodyContent = $_XPathTool.selectSingleNode($contentRoot, "//body-content") )
    $_SerializerTool.serialize($bodyContent, true)
    

    Note: The Serializer Tool is required to properly output the HTML content returned by the WYSIWYG field.

    Your RIGHT_COL region would be similar, in that you would either use a Velocity Format that uses $currentPage or applies a calling page index block so you can check the value of the radio (just to be sure whether the right column should be displayed at all) as well as the value of the WYSIWYG. Something like the following should do the trick:

    #set ( $showRightCol = $currentPage.getStructuredDataNode("display-right-col") )
    #set ( $rightColContent = $currentPage.getStructuredDataNode("right-col") )
    #if ($showRightCol.textValue == "Yes" && $rightColContent.textValue != "")
      <div class="right-col">
        $rightColContent.textValue
      </div>
    #end
    

    Or, if you would like to use a calling page index block and the XPath Tool in conjunction with the sample code to check for an empty WYSIWYG field:

    #set ( $page = $_XPathTool.selectSingleNode($contentRoot, "//calling-page/system-page") )
    #set ( $showRightCol = $_XPathTool.selectSingleNode($page, "system-data-structure/display-right-col") )
    #set ( $rightColContent = $_XPathTool.selectSingleNode($page, "system-data-structure/right-col") )
    #if ($showRightCol.value == "Yes" && ($rightColContent.value != "" || $rightColContent.getChildren().size() > 0))
      <div class="right-col">
        $_SerializerTool.serialize($rightColContent, true)
      </div>
    #end
    

    Please let me know if you have any questions.

    Thanks!

  11. 11 Posted by voltmer1 on 28 Apr, 2015 03:47 PM

    voltmer1's Avatar

    Thanks Ryan, but how is the data definition for “body-content” getting into the “DEFAULT” region on the template and not the “right-col” definition? They are both within the data definition, so what’s happening?

    Also, is there a "cheetsheet" with all the velocity methods/properties? That would help with my coding.

  12. 12 Posted by Ryan Griffith on 28 Apr, 2015 04:42 PM

    Ryan Griffith's Avatar

    Hi Steve,

    how is the data definition for “body-content” getting into the “DEFAULT” region on the template and not the “right-col” definition? They are both within the data definition, so what’s happening?

    I'm not sure if I am following your question. The Format applied to the DEFAULT region will have access to all of the structured data entered into the page's data definition, you just need to code your Format to access it.

    Also, is there a "cheetsheet" with all the velocity methods/properties?

    We have this page on our Knowledge Base as well as examples posted on Github that you can use as a reference.

    If you have a particular object/variable which you would like to see what properties/methods are available, you can use $_PropertyTool.outputProperties($variable) to print out the available properties and methods.

    Note: Replace $variable with the actual variable.

    Please let me know if you have any questions.

    Thanks!

  13. 13 Posted by voltmer1 on 28 Apr, 2015 04:54 PM

    voltmer1's Avatar

    Sorry Ryan, I had a duh moment with that first question. The format on any template system-region controls what content is fed into that system-region and how it's displayed. The identifier on the system-data-structure items allow the targeting of the items. Correct?

    Thanks for all your help. I can't promise I won't have more questions, but I think I understand the pieces better now.

  14. 14 Posted by Ryan Griffith on 28 Apr, 2015 05:13 PM

    Ryan Griffith's Avatar

    Not a problem at all, Steve. There are no silly questions here.

    The identifier on the system-data-structure items allow the targeting of the items. Correct?

    Correct, the identifiers for groups and fields are what you use to access the element, whether that is using XPath (XPath Tool), getChild() when accessing XML Elements, or getStructuredDataNode if using the Cascade API.

    I'm going to go ahead and close this discussion, please feel free to comment or reply to re-open if you have any additional questions.

    Have a great day!

  15. Ryan Griffith closed this discussion on 28 Apr, 2015 05:13 PM.

  16. voltmer1 re-opened this discussion on 28 Apr, 2015 07:21 PM

  17. 15 Posted by voltmer1 on 28 Apr, 2015 07:21 PM

    voltmer1's Avatar

    Ryan, If I am trying to do a xsl:template match for an identifier within a data definition, would I match= sytem-data-structure like this?

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="system-data-structure/right-col-head">
    <xsl:if test="right-col-head/node()">
        <div class="right-col-head">
           <copy-of select="right-col-head/node()"/>
        </div>
    </xsl:if>
    </xsl:template>
    </xsl:stylesheet>

  18. 16 Posted by Ryan Griffith on 28 Apr, 2015 08:15 PM

    Ryan Griffith's Avatar

    Hi Steve,

    Depending on whether you have an index block applied or not, the match statement may change.

    What you have currently should handle the DEFAULT region without an index block applied. Note: will want to adjust your <xsl:if> and <xsl:copy-of> statements to the following because you are already on the right-col-head element at that point:

    <xsl:template match="system-data-structure/right-col-head"> 
    <xsl:if test="./node()"> 
        <div class="right-col-head"> 
           <copy-of select="./node()"/> 
        </div> 
    </xsl:if> 
    </xsl:template>
    

    If you have an index block applied, something like the following should work:

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform&quot; version="1.0"> 
    <xsl:template match="/system-index-block"> 
      <xsl:apply-templates select="calling-page/system-page/system-data-structure/right-col-head" />
    </xsl:template> 
    <xsl:template match="right-col-head"> 
    <xsl:if test="./node()"> 
        <div class="right-col-head"> 
           <copy-of select="./node()"/> 
        </div> 
    </xsl:if> 
    </xsl:template> 
    </xsl:stylesheet>
    

    Please let me know if you have any questions.

    Thanks!

  19. 17 Posted by voltmer1 on 28 Apr, 2015 08:32 PM

    voltmer1's Avatar

    I can't get it to pull the content in for right-col-head. And I am using a calling page.

  20. 18 Posted by Ryan Griffith on 28 Apr, 2015 08:42 PM

    Ryan Griffith's Avatar

    Hi Steve,

    When you have a moment, please attach sample XML that is being applied to this Format so I can take a closer look.

    To obtain the sample XML, edit your Format and select the appropriate index block and context page within the Preview Options section at the top.

    Thanks!

  21. 19 Posted by voltmer1 on 28 Apr, 2015 08:52 PM

    voltmer1's Avatar

    BTW..I didn't know that I could do this. It looks like my format has the correct Xpath.

    <?xml version="1.0" encoding="UTF-8"?>
    <system-index-block name="calling page" type="folder" current-time="1430254227398">
        <calling-page>
            <system-page id="5c002d2289700186405084c6a0b941f2" current="true">
                <name>index</name>
                <is-published>true</is-published>
                <last-published-on>1430239206432</last-published-on>
                <last-published-by>voltmer1</last-published-by>
                <title>Home Page</title>
                <created-by>voltmer1</created-by>
                <created-on>1427472657671</created-on>
                <last-modified-by>voltmer1</last-modified-by>
                <last-modified>1430245863495</last-modified>
                <system-data-structure definition-path="Landing Page">
                    <body-content>
                        <p class="greyHead">Test Cascade Home Page</p>
                        <img alt="Steve Voltmer" class="float-right" height="220" src="site://Steves Cascade Test Site/_files/images/Steve Voltmer profile 1.jpg" width="200" />
                        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum et faucibus risus, sed dictum nulla. Maecenas dapibus elit sed magna pretium posuere. Phasellus at nunc augue. Suspendisse eget molestie est, non mollis nisi. Fusce eget leo pretium risus consectetur tempus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Morbi luctus dui at orci fringilla, ac porttitor sapien facilisis. Vivamus blandit fringilla neque in commodo. Cras tempor, nisl non ornare viverra, mi metus interdum ex, id interdum dui felis eu massa. Nulla vel dolor sit amet lectus sodales condimentum. Praesent efficitur, lorem vehicula euismod porttitor, ex risus varius arcu, a semper odio leo non arcu. Cras pellentesque iaculis suscipit.</p>
                        <p>Donec semper dui non accumsan tempus. Mauris gravida nulla tortor, condimentum lacinia neque venenatis vitae. Nam commodo varius enim sed convallis. Nulla eu dapibus augue. Vestibulum consequat felis sed magna egestas posuere. Nam elit nulla, vulputate ac suscipit at, vestibulum egestas leo. Etiam ex augue, vulputate a lacus sit amet, porttitor interdum elit. Sed volutpat justo vitae suscipit luctus.</p>
                        <p>Vestibulum et justo tellus. Quisque scelerisque interdum risus vitae ultricies. Sed tempus ante vel tellus venenatis molestie. Phasellus dictum elit vel ex molestie iaculis. In ultrices urna accumsan purus maximus gravida. Vestibulum vitae odio vitae eros iaculis semper. Sed nec felis id enim rhoncus vehicula. Cras pretium dictum urna et pretium. Vivamus sed dapibus diam, et ultrices elit. Curabitur placerat odio sed volutpat ultrices. Nullam facilisis est vitae justo tempor, quis bibendum felis cursus. In vel finibus lectus. Mauris vehicula ornare lacus eget elementum. Aenean eu dolor at libero sodales molestie sit amet sit amet mi. Nullam ultrices turpis a nulla convallis rutrum.</p>
                    </body-content>
                    <right-col-head>Right Col Header</right-col-head>
                    <display-right-col>Yes</display-right-col>
                    <right-col>Donec semper dui non accumsan tempus. Mauris gravida nulla tortor, condimentum lacinia neque venenatis vitae. Nam commodo varius enim sed convallis. Nulla eu dapibus augue. Vestibulum consequat felis sed magna egestas posuere. Nam elit nulla, vulputate ac suscipit at, vestibulum egestas leo. Etiam ex augue, vulputate a lacus sit amet, porttitor interdum elit. Sed volutpat justo vitae suscipit luctus.</right-col>
                </system-data-structure>
            </system-page>
        </calling-page>
    </system-index-block>

  22. Support Staff 20 Posted by Tim on 28 Apr, 2015 09:05 PM

    Tim's Avatar

    Hi Steve,

    Ryan stepped out for the day so I figured I'd chime in here. It looks like there may be a small issue causing the behavior you're seeing. When you have a moment, try changing:

    <copy-of select="right-col-head/node()"/>
    
    to:
    <xsl:copy-of select="right-col-head/node()"/>
    
    I believe that will do the trick.

    Let us know how things go.

    Thanks

  23. 21 Posted by voltmer1 on 29 Apr, 2015 01:29 PM

    voltmer1's Avatar

    Yeah, I noticed the missing xsl on the copy-of this morning, uhhg. I did notice, however, I can get the same results with
    <xsl:value-of select="."/> Any reason I should be using yours instead?

  24. Support Staff 22 Posted by Tim on 29 Apr, 2015 01:41 PM

    Tim's Avatar

    Any reason I should be using yours instead?

    Good question. <xsl:value-of> will return the text value of the element in question whereas <xsl:copy-of> outputs a copy of the element. If you're outputting WYSIWYG content, you'll want to use <xsl:copy-of> as that will output not only the text value of the element but also any child elements (for example, if the content contained <p>, <a>, <strong> tags, etc). If you were to use <xsl:value-of> in the same case, it would simply output those tags as text and the browser would not actually interpret them.

    Let me know if that helps!

  25. 23 Posted by voltmer1 on 29 Apr, 2015 03:54 PM

    voltmer1's Avatar

    Tim,
    One more thing that I can't wrap my head around. With this statement:

    <xls:if test="./node()">

    Isn't this looking for all the children of the context node, which would be right-col-head, but right-col-head doesn't have any children, so the test should fail, but it doesn't. What am I missing?

  26. 24 Posted by Ryan Griffith on 29 Apr, 2015 05:03 PM

    Ryan Griffith's Avatar

    Hi Steve,

    You are correct in that the . portion of the XPath will grab the context node and node() will return all nodes or text within the context node. So, this test is checking for the existence of any content/nodes within your right-col-head node.

    Please let me know if you have any questions.

    Thanks!

  27. Tim closed this discussion on 18 May, 2015 03:18 PM.

Comments are currently closed for this discussion. You can start a new one.

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac