Copied to clipboard

Flag this post as spam?

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


  • Dan 1288 posts 3921 karma points c-trib
    Jan 24, 2011 @ 17:42
    Dan
    0

    Template to iterate through media items

    Hi,

    I have a very simple gallery of images on my site, using the new schema (4.6.1).  Because this is such a basic site and there will only ever be a maximum of 5 images in the gallery (there may be fewer) and I want the UI to be as utterly simple as possible, I've decided to add 5 'media picker' data types to the gallery document type, called mainImage1, mainImage2, mainImage3, mainImage4 and mainImage5 rather than adding a container to create 'nodes' of images in a folder as I'd normally do.

    Whilst this is the simplest approach from a site admin point of view, I'm struggling with getting the most efficient XSLT to iterate through each of these image data types without repeating the code for each media item.

    This code shows the first image, but rather than repeat this whole bit of code 5 times, I'd prefer to use some kind of loop/template mechanism just to iterate over this code 5 times.  Make sense?

    <xsl:template match="/">
      <xsl:variable name="mainImage1" select="number($currentPage/mainImage1)" />
      <xsl:if test="$mainImage1 > 0">
        <xsl:variable name="mediaNode1" select="umbraco.library:GetMedia($mainImage1, 0)" />
        <xsl:if test="$mediaNode1/umbracoFile">
          <img src="{$mediaNode1/umbracoFile}" title="" alt="" />
        </xsl:if>
      </xsl:if>
    </xsl:template>

    Can anyone suggest how to template this such that I don't have to repeat the code?

    My other option is to use the 'Embedded Content' package, but I'd rather not go down the package route if possible.

    Thanks for any pointers...

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 8x admin c-trib
    Jan 24, 2011 @ 18:21
    Chriztian Steinmeier
    1

    Hi Dan,

    Here's a clean XSLT way of doing just that - ask away if you're curious:

    <?xml version="1.0" encoding="utf-8" ?>
    <xsl:stylesheet
        version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:umb="urn:umbraco.library"
        exclude-result-prefixes="umb"
    >
    
        <xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
    
        <xsl:param name="currentPage" />
    
        <xsl:template match="/">
            <!-- Process the mainImageX properties that have a value -->
            <xsl:apply-templates select="$currentPage/*[starts-with(name(), 'mainImage')][normalize-space()]" mode="media" />
        </xsl:template>
    
        <!-- Template for any media thet needs fetching - handles potential error -->
        <xsl:template match="*" mode="media">
            <xsl:variable name="mediaNode" select="umb:GetMedia(., false())" />
            <xsl:apply-templates select="$mediaNode[not(error)]" />
        </xsl:template>
    
        <!-- Template for a Media Image -->
        <xsl:template match="Image">
            <img src="{umbracoFile}" width="{umbracoWidth}" height="{umbracoHeight}" alt="{@nodeName}" />
        </xsl:template>
    
    </xsl:stylesheet>

    /Chriztian

  • Dan 1288 posts 3921 karma points c-trib
    Jan 24, 2011 @ 18:29
    Dan
    0

    Spot on!  Thanks Chriztian, that's really really useful.

  • Dan 1288 posts 3921 karma points c-trib
    Jan 25, 2011 @ 16:26
    Dan
    0

    Hi Chriztian, how would I get the alt attribute of the rendered image to be the number (position()) of that image?  So I'd end up with:

    <img src="image1.jpg" alt="0" />
    <img src="image2.jpg" alt="1" />
    <img src="image3.jpg" alt="2" />
    <img src="image4.jpg" alt="3" />
    <img src="image5.jpg" alt="4" />

    Actually, what I'm trying to do is give the first image a particular class, but the other images no class.  I've tried adding an xslt param into the first template, but I've only managed to get various errors - nothing which actually works.

    Any ideas?

    Thanks

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 8x admin c-trib
    Jan 25, 2011 @ 22:17
    Chriztian Steinmeier
    1

    Hi Dan,

    Oh man - sadly this will be the short version (the ******* thing ate my very long and detailed explanation):

    You should change the templates for "*" and "Image" to something like this:

       <!-- Template for any media that needs fetching - handles potential error -->
        <xsl:template match="*" mode="media">
            <xsl:variable name="mediaNode" select="umb:GetMedia(., false())" />
            <xsl:apply-templates select="$mediaNode[not(error)]">
                <xsl:with-param name="pos" select="position()" />
            </xsl:apply-templates>
        </xsl:template>
    
        <!-- Template for a Media Image -->
        <xsl:template match="Image">
            <xsl:param name="pos" />
            <img src="{umbracoFile}" width="{umbracoWidth}" height="{umbracoHeight}" alt="{@nodeName}">
                <xsl:if test="$pos = 1">
                    <xsl:attribute name="class">first</xsl:attribute>
                </xsl:if>
            </img>
        </xsl:template>
    
    (You need to pass the value of position() when inside the "*" template, on to the "Image" template)

    /Chriztian

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 8x admin c-trib
    Jan 25, 2011 @ 22:34
    Chriztian Steinmeier
    1

    OK - position() is a tricky bastard, so here's a mandatory exercise:

    1. Add a <xsl:value-of select="position()" /> inside the "Image" template and see what you get... OK? 11111

    2. Now move the value-of instruction into the "*" template and see what that gets you... OK? 12345

    The value of position() is evaluated in the "current set" which roughly translates to the apply-templates context, and the "Image" template is applied 5 times with a set of one node, whereas the "*" template is applied a single time with a set of 5 nodes.

    /Chriztian

  • Dan 1288 posts 3921 karma points c-trib
    Jan 26, 2011 @ 10:31
    Dan
    0

    Chriztian, thanks again, that's worked a treat.  I was fumbling along the right lines but as you mentioned in your last post I had the position() in the wrong template, so it was always passing through 1.  Thank you!

Please Sign in or register to post replies

Write your reply to:

Draft