Mark
Mark

Reputation: 10182

How can I properly hide a list of XSL processed XML elements using javascript

Good morning. I have an XML file which contains lists of warning and errors from a build output. I have successfully been able to write XSL to iterate over the separate lists of warnings and errors to have them display in my browser. What I'd like to do next would be to add a bit of javascript in order to add a link/button to be able to toggle the display of the warnings. I can't get it to work properly.

here is the relvant code (trimmed down to what I hope are the essentials)

<xsl:template match="/">
    <xsl:variable name="messages" select="/cruisecontrol//buildresults//message" />
    <xsl:variable name="warning.messages" select="$messages[(contains(text), 'warning ')) or @level='Warning']" />
    <xsl:variable name="warning.messages.count" select="count($warning.messages)" />
    <xsl:if test="$warning.messages.count > 0">
        <script type="text/javascript">
            function toggleWarnings() {
                eDiv = document.getElementById("warnings");
                tDiv = document.getElementById("warningsTitle");
                if ( eDiv.style.display == "none" ) {
                    eDiv.style.display = "inline";
                    tDiv.innerText = "Hide Warnings";
                } else {
                    tDiv.innerText = "View Warnings";
                    eDiv.style.display = "none";
                }
            }
        </script>
        <table>
            <tr> <td>
                <a href="javascript:void()" onclick="javascript:toggleWarnings(); return false;">
                   <span id="warningsTitle">View Warnings</span>
                </a>
            </td> </tr>
            <xsl:for-each select="$warning.messages">
                <tr> <td class="warning" id="warnings" style="display: none;">
                    <xsl:value-of select="."/>
                </td> </tr>
            </xsl:for-each>
        </table>

The problemt that I have is that only one warning is ever displayed after hitting the "view warnings" link. My problem is that I know enough HTML, XSL, and javascript to be slightly dangerous and the combination is proving that I don't know enough :-)

Is there an easy way for me to iterate over XSL elements, display then in a table and also be able to hide all of those elements under a link toggle?

Thanks.

Upvotes: 2

Views: 3140

Answers (1)

Greg
Greg

Reputation: 321786

Give this a go - comments are in the code.

<xsl:template match="/">
<xsl:variable name="messages" select="/cruisecontrol//buildresults//message" />
<xsl:variable name="warning.messages" select="$messages[(contains(text), 'warning ')) or @level='Warning']" />
<xsl:variable name="warning.messages.count" select="count($warning.messages)" />
<xsl:if test="$warning.messages.count > 0">
    <script type="text/javascript">
        function toggleWarnings()
        {
            // Get the table
            var table = document.getElementById("warnings");

            // Get all the rows in the table
            var rows = table.getElementsByTagName('tr');

            tDiv = document.getElementById("warningsTitle");

            if (tDiv.innerHTML == 'View Warnings')
            {
                for (var i = rows.length - 1; i >= 0; i--)
                {
                    // Skip any rows that aren't warnings
                    if (rows[i].className != 'warning')
                        continue;

                    try
                    {
                        // Try it the right way
                        rows[i].style.display = 'table-row';
                    }
                    catch (e)
                    {
                        // Try it the IE way
                        rows[i].style.display = 'block';
                    }

                tDiv.innerHTML = "Hide Warnings";
            }
            else
            {
                for (var i = rows.length - 1; i >= 0; i--)
                {
                    // Skip any rows that aren't warnings
                    if (rows[i].className != 'warning')
                        continue;

                    rows[i].style.display = 'none';
                }

                tDiv.innerHTML = "View Warnings";
            }

            return false;
        }
    </script>
    <!-- Moved the ID to the table - IDs must be unique! -->
    <table id="warnings">
        <tr>
            <td>
                <!-- This is must shorter, and "javascript:" inside onclick is plain wrong -->
                <a href="#" onclick="return toggleWarnings();">
                    <span id="warningsTitle">View Warnings</span>
                </a>
            </td>
        </tr>
        <xsl:for-each select="$warning.messages">
            <!-- Moved the class to the tr -->
            <tr class="warning" style="display: none;">
                <td>
                    <xsl:value-of select="."/>
                </td>
            </tr>
        </xsl:for-each>
    </table>

Upvotes: 3

Related Questions