Copied to clipboard

Flag this post as spam?

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


  • tesuji 95 posts 139 karma points
    Mar 01, 2010 @ 23:32
    tesuji
    0

    Random quotes, images

    My client wants to include random images and quotes on a web page. I need to pick randomly from a collection of existing images and quotes. (It doesn't have to be exactly random, but something similar - to be different with a new page load). 

    Does Umbraco do this already, or are there sample code or packages I can use? 

    I think .NET has an ad rotator control. Would it be easiest to just put this in a user control?

  • Jesper Hauge 298 posts 487 karma points c-trib
    Mar 01, 2010 @ 23:57
    Jesper Hauge
    0

    If you're doing this from a usercontrol - you can create an extension method to the umbraco.presentation.nodeFactory.Node class, that selects a random child node like this:

    using System;
    using umbraco.presentation.nodeFactory;
    
    namespace My.Umbraco.Extensions
    {
      public static class UmbracoExt
      {
        /// <summary>
        /// Returns a random childnode from provided node
        /// </summary>
        /// <param name="node">node to look in</param>
        /// <returns>Node</returns>
        public static Node GetRandomChild(this Node node)
        {
          if (node.Children.Count == 0)
            return null;
          if (node.Children.Count == 1)
            return node.Children[0];
          var rnd = new Random(DateTime.Now.Millisecond);
          return node.Children[rnd.Next(0, node.Children.Count)];
        }
      }
    }

    This enables getting a random child node and its data like this in the codebehind:

    using System;
    using System.Web;
    using System.Web.UI;
    using My.Umbraco.Extensions;
    using umbraco;
    using umbraco.BusinessLogic;
    using umbraco.presentation.nodeFactory;
    
    namespace petersen_gruppen.dk.usercontrols
    {
        public partial class TopPic : System.Web.UI.UserControl
        {
            protected void Page_Load(object sender, EventArgs e)
            {
                var currentNode = Node.GetCurrent();
                var picNode = currentNode.GetRandomChild()
                yourImg.Src = picNode.GetProperty("umbracoFile").Value;
                quoteLiteral.Text = picNode.GetProperty("quoteText").Value;
            }
        }
    }

    This code assumes you that the docs with quotes/images is childnodes to the current page, if not you can select the currentNode from its id. It also assumes you have a series of nodes of a doctype that has an upload field named "umbracoFile" for the image and a text property named "quoteText" for the text.

    Hope this will give you an idea.

    Regards
    Jesper Hauge

  • Douglas Robar 3570 posts 4711 karma points MVP ∞ admin c-trib
    Mar 02, 2010 @ 00:13
    Douglas Robar
    0

    This can also be done in XSLT.

    Here's an example that uses ImageGen to make a thumbnail of a random image. The hard-coded variables could certainly be passed in as macro variables instead.

    In my example, I was making a portfolio. I pre-loaded the full-size portfolio images into the Media section. I then added a Media Picker property to my portfolio docType for the associated image.  I put all my portfolio pages below a single content page (the $folder varaiable in my code). Then the macro could simply select a random node from below the $folder page and display the thumbnail using ImageGen to resize it to any size I wanted.

     

    <?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:umbraco.library="urn:umbraco.library"
    xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath"
    exclude-result-prefixes="msxml umbraco.library Exslt.ExsltMath">


    <xsl:output method="xml" omit-xml-declaration="yes"/>

    <xsl:param name="currentPage"/>
    <xsl:variable name="folder" select="1158"/>
    <xsl:variable name="thumbnailHeight" select="60"/>

    <!-- ============================================================= -->

    <xsl:template match="/">

    <xsl:variable name="imageID">
    <xsl:call-template name="GetRandomNode"/>
    </xsl:variable>

    <img alt="Portfolio">
    <xsl:attribute name="src">
    <xsl:text>/umbraco/imagegen.aspx?image=</xsl:text><xsl:value-of select="umbraco.library:GetMedia($imageID, 0)/data [@alias='umbracoFile']"/><xsl:text>&amp;height=</xsl:text><xsl:value-of select="$thumbnailHeight"/>
    </xsl:attribute>
    </img>
    </xsl:template>

    <!-- ============================================================= -->

    <xsl:template name="GetRandomNode">
    <xsl:variable name="numNodes" select="count(umbraco.library:GetXmlNodeById($folder)/node)"/>
    <xsl:variable name="random" select="floor(Exslt.ExsltMath:random() * $numNodes) + 1"/>

    <xsl:choose>
    <xsl:when test="umbraco.library:GetXmlNodeById($folder)/node [position() = $random] [string(data [@alias='umbracoNaviHide']) != '1'] ">
    <xsl:value-of select="umbraco.library:GetXmlNodeById($folder)/node [position() = $random]/data [@alias='image']"/>

    </xsl:when>
    <xsl:otherwise>
    <xsl:call-template name="GetRandomNode"/>
    </xsl:otherwise>
    </xsl:choose>

    </xsl:template>

    <!-- ============================================================= -->

    </xsl:stylesheet>

    cheers,
    doug.

  • tesuji 95 posts 139 karma points
    Mar 02, 2010 @ 21:39
    tesuji
    0

    Thanks for the replies. Very helpful

  • Arjan H. 226 posts 463 karma points c-trib
    Mar 25, 2010 @ 21:56
    Arjan H.
    0

    Be careful using the XSLT provided by Douglas. The script can cause an infinite loop, since the template GetRandomNode keeps repeating itself when it bumps into a:

    node [string(data [@alias='umbracoNaviHide']) != '1']

    The biggest problem is when you try to save the XSLT, because saving the XSLT can mysterically cause the w3wp.exe process to absorb 100% of the CPU (on /umbraco/webservices/codeeditor.save.asmx) until you recycle the application pool or restart IIS althogether. I've tested the code on multiple servers, all with the same results. Does anyone have any idea why that happens?

    I rewrote the XSLT to a very basic version that fetches a random nodeID from all pages of document type RunwayTextpage:

    <?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:umbraco.library="urn:umbraco.library" xmlns:Exslt.ExsltCommon="urn:Exslt.ExsltCommon" xmlns:Exslt.ExsltDatesAndTimes="urn:Exslt.ExsltDatesAndTimes" xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath" xmlns:Exslt.ExsltRegularExpressions="urn:Exslt.ExsltRegularExpressions" xmlns:Exslt.ExsltStrings="urn:Exslt.ExsltStrings" xmlns:Exslt.ExsltSets="urn:Exslt.ExsltSets" 
        exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets ">
    
    <xsl:output method="xml" omit-xml-declaration="yes"/>
    <xsl:variable name="documentTypeAlias" select="string('RunwayTextpage')"/>
    
    <xsl:param name="currentPage"/>
    
    <xsl:template match="/">
        <xsl:variable name="randomNodeID">
            <xsl:call-template name="GetRandomNodeID"/>
        </xsl:variable>
    
        <p><xsl:value-of select="$randomNodeID"/></p>
    </xsl:template>
    
    <xsl:template name="GetRandomNodeID">
        <xsl:variable name="numNodes" select="count($currentPage/ancestor-or-self::node[@level = 1]//node[@nodeTypeAlias = $documentTypeAlias and string(data [@alias='umbracoNaviHide']) != '1']) "/>
            <xsl:variable name="random" select="floor(Exslt.ExsltMath:random() * $numNodes) + 1"/>
    
        <xsl:if test="$currentPage/ancestor-or-self::node[@level = 1]//node[@nodeTypeAlias = $documentTypeAlias] [position() = $random]">
            <xsl:value-of select="$currentPage/ancestor-or-self::node[@level = 1]//node[@nodeTypeAlias = $documentTypeAlias] [position() = $random]/@id"/>
        </xsl:if>
    </xsl:template>
    
    </xsl:stylesheet>

  • Rich Green 2246 posts 4008 karma points
    Apr 12, 2010 @ 10:11
    Rich Green
    0

    Hi,

    Many thanks for supplying the code guys, very useful.

    Arjan, are you saying your code example has this issue as well or have you written in a way that avoids this issue?

    Doug, have you ever seen this issue with Umbraco using your code? 

    Many thanks

    Rich

  • Arjan H. 226 posts 463 karma points c-trib
    Aug 06, 2010 @ 00:27
    Arjan H.
    0

    Rich, my version of the script doesn't cause an infinite loop.

Please Sign in or register to post replies

Write your reply to:

Draft