Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • trfletch 598 posts 604 karma points
    Nov 09, 2009 @ 15:59
    trfletch
    0

    Randomly select node and display content

    Hi,

    I have a section on my Umbraco V4 website that is for testimonials from clients, it is structured as follows:

    Testimonials section
      - Testimonial 1
      - Testimonial 2
      - Testimonial 3

    I want to create an XSLT that picks a random node from the testimonial section so that I show a customer comment on each page. Can anyone give me any help regarding this?

     

  • Lee Kelleher 4026 posts 15836 karma points MVP 13x admin c-trib
    Nov 09, 2009 @ 16:14
    Lee Kelleher
    2

    Hi trfletch,

    Here's an XSLT snippet that I posted on the old forum:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp "&#x00A0;"> ]>
    <xsl:stylesheet
        version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:msxml="urn:schemas-microsoft-com:xslt"
        xmlns:msxsl="urn:schemas-microsoft-com:xslt"
        xmlns:bdk="http://bodenko.com"
        xmlns:umbraco.library="urn:umbraco.library"
        exclude-result-prefixes="msxml msxsl umbraco.library bdk">
        <xsl:output method="xml" omit-xml-declaration="yes" />
    
        <xsl:param name="currentPage" />
        <xsl:variable name="maxItems" select="number(5)" />
    
        <msxsl:script language="JavaScript" implements-prefix="bdk">
            function Random(r) { return Math.ceil(Math.random()*r); }
        </msxsl:script>
    
        <xsl:template match="/">
            <xsl:for-each select="$currentPage/ancestor-or-self::node[@level=1]/descendant-or-self::node[@nodeTypeAlias='Testimonial']">
                <xsl:sort select="bdk:Random($maxItems)" order="descending" />
                <xsl:if test="position() &lt;= $maxItems">
                    <xsl:value-of select="@nodeName" /><br />
                </xsl:if>
            </xsl:for-each>
        </xsl:template>
    </xsl:stylesheet>

    Set the "maxItems" variable to the number of testimonials that you want to display (probably 1 in your case).  Set the @nodeTypeAlias to whatever your doc-type alias is for the testimonials (I guessed it was "Testimonial").

    The idea here is that the for-each performs a random sort... rather than a random selection ... it still has the same effect (unless you are dealing with hundreds/thousands of nodes - then there'll be a performance hit - but for a few nodes, it's fine).

    Cheers, Lee.

  • Dirk De Grave 4541 posts 6021 karma points MVP 3x admin c-trib
    Nov 09, 2009 @ 16:14
    Dirk De Grave
    0

    Hi,

    Have a look at Tim's blog post. He's done a similar thing...

     

    Cheers,

    /Dirk

  • Ricky Beard 61 posts 116 karma points
    Nov 09, 2009 @ 16:34
    Ricky Beard
    0

    I voted up Lee's approuch.  I used his example a while ago to do exactly what you are trying to do (display random testimonials). You can see the result here: http://www.nceexam.com.

  • Lee Kelleher 4026 posts 15836 karma points MVP 13x admin c-trib
    Nov 09, 2009 @ 17:17
    Lee Kelleher
    0

    Cheers Ricky, glad that I could help (for a while ago!)

  • trfletch 598 posts 604 karma points
    Nov 09, 2009 @ 18:29
    trfletch
    0

    Hi,

    Thanks for the responses, I have tried Lee's method and it works fine if I have more than 1 in the maxitems variable but I only actually want one testimonial displayed on the page and if I put 1 in the maxitems variable it just shows the same one everytime (the first node in the list). Any ideas?

  • Chris Koiak 700 posts 2626 karma points
    Nov 09, 2009 @ 19:35
    Chris Koiak
    0

    A modification to just get one item count be something like...

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp "&#x00A0;"> ]>
    <xsl:stylesheet
           
    version="1.0"
           
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
           
    xmlns:msxml="urn:schemas-microsoft-com:xslt"
           
    xmlns:msxsl="urn:schemas-microsoft-com:xslt"
           
    xmlns:bdk="http://bodenko.com"
           
    xmlns:umbraco.library="urn:umbraco.library"
           
    exclude-result-prefixes="msxml msxsl umbraco.library bdk">
           
    <xsl:output method="xml" omit-xml-declaration="yes" />

           
    <xsl:param name="currentPage" />

           
    <msxsl:script language="JavaScript" implements-prefix="bdk">
                    function Random(r) { return Math.ceil(Math.random()*r); }
           
    </msxsl:script>

           
    <xsl:template match="/">

                   
    <xsl:variable name="testimonialNodes" select="$currentPage/ancestor-or-self::node[@level=1]/descendant-or-self::node[@nodeTypeAlias='Testimonial']">
                   
    <xsl:value-of select="testimonialNodes[bdk:Random(count($testimonialNodes))]" /><br />
                   

           
    </xsl:template>
    </xsl:stylesheet>
  • trfletch 598 posts 604 karma points
    Nov 10, 2009 @ 10:18
    trfletch
    0

    Thanks Chris, I can sort of see how your code may randomly find one of the nodes but how do I then get it to display some data from that node? Such as the node name?

  • Chris Koiak 700 posts 2626 karma points
    Nov 10, 2009 @ 11:31
    Chris Koiak
    0

    Once you have the node you can use standard xpath to get any data

    <xsl:value-of select="testimonialNodes[bdk:Random(count($testimonialNodes))]/data[@alias='PageTile']" />

    or

    <xsl:value-of select="testimonialNodes[bdk:Random(count($testimonialNodes))]/@nodeName" />
  • trfletch 598 posts 604 karma points
    Nov 10, 2009 @ 13:52
    trfletch
    0

    Hi Chris,

    Thanks again for your help, this appears to be working partly if I add $ to the front of testimonialNodes on value of select like so:

     <xsl:value-of select="$testimonialNodes[bdk:Random(count($testimonialNodes))]/data[@alias='testimonialsnippet']" />

    I say partly because every now and then it shows nothing as if it is finding a node without any data in the testimonialsnippet property but all the Testimonial nodes have data in this property. Although this does bring me to another question which would be how do I get it to only find the ones that do have data in that property type (I may have testimonials that do not have anything for that property).

  • Chris Koiak 700 posts 2626 karma points
    Nov 10, 2009 @ 14:32
    Chris Koiak
    0

    I think you'd benefit from reading upon xslt. It'll make fixing simple or syntax issues much quicker.

    Have a read at http://our.umbraco.org/wiki/reference/xslt (see sub pages in right hand side)

     

  • trfletch 598 posts 604 karma points
    Nov 10, 2009 @ 15:12
    trfletch
    0

    Thanks Chris,

    I have read that before and do have a basic understanding of XSLT and I have created many lists and menu's using it but I have never created one with Javascript in to select random nodes therefore I do not really understand what that part of it is trying to do. This is what I currently have:

    <xsl:param name="currentPage" />
           <msxsl:script language="JavaScript" implements-prefix="bdk">
                    function Random(r) { return Math.ceil(Math.random()*r); }
            </msxsl:script>


            <xsl:template match="/">
     <div class="testimonialstitle">
     Our clients say:
     </div>
                    <xsl:variable name="testimonialNodes" select="umbraco.library:GetXmlNodeById(1085)/node [string(data [@alias='testimonialsnippet']) != '']"/>
            <xsl:value-of select="$testimonialNodes[bdk:Random(count($testimonialNodes))]/data[@alias='testimonialsnippet']" /><br />
            </xsl:template>

     

    It is showing random testimonials like I want but every now and then it shows nothing and I can't work out why it is doing it, I have added the following to the variable:

    [string(data [@alias='testimonialsnippet']) != '']

    which I hoped would make it only show testimonials if they had something in the testimonialsnippet property (even though at the moment they all do) but this did not solve the problem.

  • Chris Koiak 700 posts 2626 karma points
    Nov 10, 2009 @ 15:36
    Chris Koiak
    0

    You definately seem on the right track, I can't see why that would return blank values.

  • trfletch 598 posts 604 karma points
    Nov 10, 2009 @ 15:57
    trfletch
    0

    Yes I know it is very strange, I have just republished the entire site clearing the cache to see if that helped but it has not resolved the issue. Is there anyone else out there that can shed any light on this?

  • trfletch 598 posts 604 karma points
    Nov 11, 2009 @ 14:09
    trfletch
    0

    Can anyone see what is causing my issue above or does anyone know of an alternative method to randomly show the content from a node? Thanks in advance for any help offered.

  • trfletch 598 posts 604 karma points
    Nov 12, 2009 @ 11:27
    trfletch
    0

    Can anyone help at all with this? I have been going over this for ages now, I currently have the following code:

           <msxsl:script language="JavaScript" implements-prefix="bdk">
                    function Random(r) { return Math.ceil(Math.random()*r); }
            </msxsl:script>
            <xsl:template match="/">
    <xsl:variable name="testimonialNodes" select="umbraco.library:GetXmlNodeById(1085)/node [string(data [@alias='testimonialsnippet']) != '']" />
    <xsl:for-each select="$testimonialNodes[bdk:Random(count($testimonialNodes))] " >
    <xsl:value-of select="data [@alias = 'testimonialsnippet']"/>
    </xsl:for-each>

    I was under the impression that:

    <xsl:variable name="testimonialNodes" select="umbraco.library:GetXmlNodeById(1085)/node [string(data [@alias='testimonialsnippet']) != '']" />

    should be creating a variable called testimonialNodes that is child nodes of node 1085 where the testimonialsnippet property is not blank but somehow I am still getting a blank output every now and then! It just doesn't make sense. Is my XSLT wrong in some way or is this some sort of bug?

  • trfletch 598 posts 604 karma points
    Nov 12, 2009 @ 13:06
    trfletch
    0

    Another issue I have just noticed is that it also sometimes displays more than one testimonial.

  • trfletch 598 posts 604 karma points
    Nov 12, 2009 @ 15:12
    trfletch
    0

    Ok I have finally resolved this, just in case anyone is interested the code I used to get it working is as follows, it's a shame you can't mark your own posts as the solution!

     <xsl:variable name="maxItems" select="number(1)" />
      <xsl:template match="/">
    <div class="testimonialstitle">
     Our clients say:
     </div>
          <xsl:for-each select="umbraco.library:GetXmlNodeById(1085)//node">
            <xsl:sort select="randomTools:GetRandom(0,count(umbraco.library:GetXmlNodeById(1085)//node))" order="ascending" />
            <xsl:if test="position() &lt;= $maxItems">
             <span class="testimonialstext">
      <img src="/images/start-quote.jpg"/>
      <xsl:value-of select="data [@alias = 'testimonialsnippet']"/>
      <img src="/images/end-quote.jpg"/>
      </span>
           </xsl:if>
          </xsl:for-each>
      </xsl:template>



      <msxsl:script language="c#" implements-prefix="randomTools">
        <msxsl:assembly href="../bin/umbraco.dll"/>
        <![CDATA[
            /// <summary>
            /// Gets a random integer that falls between the specified limits
            /// </summary>
            /// <param name="lowerLimit">An integer that defines the lower-boundary of the range</param>
            /// <param name="upperLimit">An integer that defines the upper-boundary of the range</param>
            /// <returns>A random integer within the specified range</returns>
            public static int GetRandom(int lowerLimit,int upperLimit) {
                Random r = umbraco.library.GetRandom();
                int returnedNumber = 0;
                lock (r)
                {
                    returnedNumber = r.Next(lowerLimit, upperLimit);
                }
                return returnedNumber;
            }
        ]]>
      </msxsl:script>
Please Sign in or register to post replies

Write your reply to:

Draft