2

I'm trying to create a carousel presentation of list items as "slides" using a DataFormWebPart. I've set the Data View's paging to Display sets of 1 item. I've pulled as much of the mucky tables from the code as I could, and replaced the stock paging icons, and it displays and advances to the next list item properly.

The issue I've encountered is the with the "previous set" action that, when it works, would display the list item previous the currently displayed item. When clicked, the entire page is sent "back" as if I'd clicked the browser's back button.

Here's what I believe is the relevant template sections...

<xsl:template name="dvt_1.navigation">
<xsl:param name="FirstRow" />
<xsl:param name="LastRow" />
<xsl:param name="RowLimit" />
<xsl:param name="dvt_RowCount" />
<xsl:param name="RealLastRow" />
<xsl:variable name="PrevRow">
    <xsl:choose>
        <xsl:when test="$FirstRow - $RowLimit &lt; 1">1</xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$FirstRow - $RowLimit" />
        </xsl:otherwise>
    </xsl:choose>
</xsl:variable>
<xsl:variable name="LastRowValue">
    <xsl:choose>
        <xsl:when test="$LastRow &gt; $RealLastRow">
            <xsl:value-of select="$LastRow"></xsl:value-of>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$RealLastRow"></xsl:value-of>
        </xsl:otherwise>
    </xsl:choose>
</xsl:variable>
<xsl:variable name="NextRow">
    <xsl:value-of select="$LastRowValue + 1"></xsl:value-of>
</xsl:variable>
<xsl:if test="$dvt_firstrow &gt; 1" ddwrt:cf_ignore="1">
    <a>
        <xsl:attribute name="href">javascript: history.back();</xsl:attribute>
        <img src="/gmcc/assets/ui/carousel_left.png" border="0" alt="Previous" />
    </a>
</xsl:if>
<xsl:if test="$LastRowValue &lt; $dvt_RowCount or string-length($dvt_nextpagedata)!=0" ddwrt:cf_ignore="1">
    <a>
        <xsl:attribute name="href">
            javascript: <xsl:value-of select="ddwrt:GenFireServerEvent(concat('dvt_firstrow={',$NextRow,'};dvt_startposition={',$dvt_nextpagedata,'}'))" />;
        </xsl:attribute>
        <img src="/gmcc/assets/ui/carousel_right.png" border="0" alt="Next" />
    </a>
</xsl:if>

And I've isolated the code for the paging controls:

<xsl:if test="$dvt_firstrow &gt; 1" ddwrt:cf_ignore="1">
    <a>
        <xsl:attribute name="href">javascript: history.back();</xsl:attribute>
        <img src="/gmcc/assets/ui/carousel_left.png" border="0" alt="Previous" />
    </a>
</xsl:if>
<xsl:if test="$LastRowValue &lt; $dvt_RowCount or string-length($dvt_nextpagedata)!=0" ddwrt:cf_ignore="1">
    <a>
        <xsl:attribute name="href">
            javascript: <xsl:value-of select="ddwrt:GenFireServerEvent(concat('dvt_firstrow={',$NextRow,'};dvt_startposition={',$dvt_nextpagedata,'}'))" />;
        </xsl:attribute>
        <img src="/gmcc/assets/ui/carousel_right.png" border="0" alt="Next" />
    </a>

It uses an if statement and applies a javascript action based on the outcome. I'm not savvy in XML/XSLT to know if I can correct the issue by editing the if statement, but I can see that the "back" javascript is a simple javascript: history.back();, whereas the "next" is a more complicated javascript: <xsl:value-of select="ddwrt:GenFireServerEvent(concat('dvt_firstrow={',$NextRow,'};dvt_startposition={',$dvt_nextpagedata,'}'))" />;

I've tried some guesses as to how I can copy, then modify, the "next" code to create antonymous "previous" code, but I can't seem to figure out what I need, either in the JavaScript or the XSLT. I want clicking the left bracket to display the previous list item, and I'm stuck.

1

Try changing

<xsl:attribute name="href">
      javascript: <xsl:value-of select="ddwrt:GenFireServerEvent(concat('dvt_firstrow={',$NextRow,'};dvt_startposition={',$dvt_nextpagedata,'}'))" />;
</xsl:attribute>

To

<xsl:attribute name="href">
      javascript: <xsl:value-of select="ddwrt:GenFireServerEvent(concat('dvt_firstrow={',$FirstRow - $XmlDefinition/RowLimit,'};dvt_startposition={',$dvt_prevpagedata,'}'))" />;
</xsl:attribute>
  • Your solution looks like it might do the same thing as the solution I reference, but with less code. I didn't see where you created the variable $dvt_prevpagedata... Did I completely miss that this variable already existed and I just needed to invoke it? I'm looking forward to trying out your solution when this comes up again. Thanks! – Pete Apr 5 '16 at 5:56
  • The variable $dvt_prevpagedata is included in the OOTB Pagination template. :) – Kitty Dunle Apr 5 '16 at 22:26
0

You say it is in this code:

<xsl:if test="$LastRowValue &lt; $dvt_RowCount or string-length($dvt_nextpagedata)!=0" ddwrt:cf_ignore="1">
    <a>
        <xsl:attribute name="href">
            javascript: <xsl:value-of select="ddwrt:GenFireServerEvent(concat('dvt_firstrow={',$NextRow,'};dvt_startposition={',$dvt_nextpagedata,'}'))" />;
        </xsl:attribute>
        <img src="/gmcc/assets/ui/carousel_right.png" border="0" alt="Next" />
    </a>

Since you don't claim about the first xsl:if. Since you are new to XSLT, let me try to help you by dissecting it. You didn't show example input XML and expected output of this if-statement or the transformation as a whole, but let me give it a try regardless:

<xsl:if test="$LastRowValue &lt; $dvt_RowCount or string-length($dvt_nextpagedata)!=0" ddwrt:cf_ignore="1">

xsl:if evaluates the XPath statement in test and if true, evaluates its body. ddwrt:cf_ignore="1" can be ignored, it is a mystery, even to seasoned SP developers.

$LastRowValue &lt; $dvt_RowCount or string-length($dvt_nextpagedata)!=0

The expression in the xsl:if. Read &lt; as < (since XSLT is written in XML, just like in XML, < and some other characters must be escaped as character entities). Variables are started with $. What's in it, only you can tell. Obviously, this code does something like:

  • If last row value is less then the row count (i.e., we are not on the last page)
  • or the string length of the next page's data is nonzero (i.e., there is a next page)
  • then execute this block
   <a>
       <xsl:attribute name="href">

In XSLT, anything not prefixed with xsl: is considered a literal result element (or an extension instruction, but let's not go there). Writing <br /> in an XSLT stylesheet means "print <br /> to the output". Here we are writing the body of an <a> with in it an attribute (the href of the <a> element).

       javascript: <xsl:value-of select="
           ddwrt:GenFireServerEvent(
           concat('dvt_firstrow={',
               $NextRow,
               '};dvt_startposition={',
               $dvt_nextpagedata,
               '}')
       )" />;

Since whitespace is not significant in an attribute, I have taken the liberty to try to make this readable. This looks like:

"javascript: " + X + ";"

Where X is the value-of instruction. Just like a literal result element, literal text creates a literal text node. In this code that is "javascript: " and ";" (before and after <xsl:value-of.../>). Then, the xsl:value-of does nothing more than taking whatever is in its select-expression and converting it to a string value.

Inside this select-expression, we find concat(a, b, c, d, e), which just means concatenate these string values, something like:

"dvt_firstrow={" + $NR + "};dvt_startposition={" + $NPD + "}"

So, if I assume that $NR (next row) is an integer and $NPD (next page data) is an integer too, this becomes something like:

"dvt_firstrow={123};dvt_startposition={42}"

This is then given to the outer function here, ddwrt:GenFireServerEvent. I have no idea what that does, it is something from SharePoint and I have never had to deal with that function directly.

<img src="/gmcc/assets/ui/carousel_right.png" border="0" alt="Next" />

This is yet another literal result element, nothing fancy here, it is jsut an image inside your <a>.

That concludes the dissection of your code. Hopes this helps you find the issue. I don't know what ddwrt:GenFireServerEvent expects as an argument, but if something goes wrong currently, I would take a look there. You can add xsl:comment statements in the stylesheet to create comments that are rendered in the HTML as <!-- your comment -->, you can use that for diagnostics without disrupting your page.

  • Abel, my immense thanks to you. I'll need to go over this again, but this is an incredible breakdown of what's happening in the code I provided. Thank you for taking the time to help educate me! – Pete Sep 13 '15 at 1:47
  • I think I've followed your reply enough to think the issue isn't the ddwrt:GenFireServerEvent, specifically. In reading msdn.microsoft.com/en-us/library/…, it's likely a server call to get the next item for the javascript to load on clicking the "next" button. I think I need the equivalent "previous" code to use on the "previous" button. The code for "next" seems to use values from variables created earlier in the code, I think I need the antonyms for $NextRow and $dvt_nextpagedata and their xslt arguments. – Pete Sep 14 '15 at 16:31
0

I found an article about paging problems in the dataview webpart where the solution was creating a new variable called dvt_PrevPageData

<xsl:variable name="dvt_PrevPageData">
    <xsl:choose>
        <xsl:when test="($FirstRow - $RowLimit - 1) &gt; -1">
            <xsl:value-of select="$FirstRow - $RowLimit - 1" />
        </xsl:when>
        <xsl:otherwise>0</xsl:otherwise>
    </xsl:choose>
</xsl:variable>

and then replacing the this code from the paging block

<xsl:attribute name="href">javascript: history.back();</xsl:attribute>

with the following:

<xsl:attribute name="href">
    javascript: <xsl:value-of select="ddwrt:GenFireServerEvent(concat('dvt_firstrow={',$PrevRow,'};dvt_startposition={Paged=TRUE&amp;p_ID=',$dvt_PrevPageData,'}'))" />;
</xsl:attribute>

It appears to be the antonym to the "next" code in the paging section. Works like a charm.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.