Copied to clipboard

Flag this post as spam?

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


  • MartinB 411 posts 512 karma points
    Aug 07, 2010 @ 14:10
    MartinB
    0

    Recursive macro for a banner

    Hi there

    On my site i need a recursive banner that'll display on child nodes if nothing else is selected in a mediapicker property.

    On my home page i have a macro, but i found i have to make the xslt recursive as recursive="true" won't work for macro's.

    In my xslt i have the following:

    select="umbraco.library:GetMedia($currentPage/data[@alias='bannerImage'], 0)/data"

    This works if i edit each node and manually pick an image to use as banner, but i need it to display a default banner on all child nodes until someone chooses to insert another banner on one of the child nodes.

    I've tried to find the solution on the forum and tried things such as:

    <xsl:variable name="media" select="umbraco.library:GetMedia($currentPage/ancestor-or-self::* /data[@alias='bannerImage'], 0)/data" />

    But not quite correct.

    Can someone lead me in the direction of a solution to this?

    Thanks in advance.

  • MartinB 411 posts 512 karma points
    Aug 07, 2010 @ 14:31
    MartinB
    0

    Ok, found it:

    <xsl:variable name="media" select="umbraco.library:GetMedia($currentPage/ancestor-or-self::node/data[@alias='bannerImage'], 0)/data" />

    I had two pages with the same name, that's why didn't work at first.

  • MartinB 411 posts 512 karma points
    Aug 07, 2010 @ 14:33
    MartinB
    0

    Gah, not quite.

    Now i have the banner image from my top node on all child nodes, but if i choose another image on one of my child nodes, i still shows the top node banner image.

    Any thoughts?

  • Matt Brailsford 4124 posts 22215 karma points MVP 9x c-trib
    Aug 07, 2010 @ 14:34
    Matt Brailsford
    1

    Hi Martin,

    You can just use a recursive property for your macro.

    If you setup a property on your macro, then when you drop it in your template, set the macros property as follows:

    <umbraco:macro alias="myMacroAlias" runat="server" myMacroPropertyAlias="[$myDocTypePropertAlias]" />

    The [$...] syntax tells umbraco to look on the current page for a property with that name, if it can't be found, recursivly move back up the tree untill it does.

    Matt

  • MartinB 411 posts 512 karma points
    Aug 07, 2010 @ 14:38
    MartinB
    0

    Hi Matt

    I actually had a look at one of your posts regarding this but didn't figure it out until now.

    Awesome-O virtual high five!

  • MartinB 411 posts 512 karma points
    Aug 08, 2010 @ 22:41
    MartinB
    0

    Hi again Matt

    I don't know what just happened but i have some troubles getting this to work now.

    My structure is like so:

    Container page with a redirect to frontpage

    Container

    - Frontpage

    - page 2

    - page 3

    i'm using this macro in my masterpage file: <umbraco:macro alias="BannerImageLeft" runat="server" myMacroPropertyAlias="[$bannerImageLeft]" />

    I've made a property called Banner Image Left with the alias bannerImageLeft

    My macro is called: Banner Image Left    and macro alias is: BannerImageLeft

    xslt is like this:

     <xsl:variable name="media" select="umbraco.library:GetMedia($currentPage/data[@alias='bannerImage'], 0)/data" />

        <xsl:if test="$media">
          <xsl:variable name="url" select="$media [@alias = 'umbracoFile']" />
          <xsl:variable name="width" select="$media [@alias = 'umbracoWidth']" />
          <xsl:variable name="height" select="$media [@alias = 'umbracoHeight']" />
          <img src="{$url}" width="{$width}" height="{$height}" />
        </xsl:if>

    The only places i get banners is the pages i manually picked one for eventhough i've picked the banners on my container, it doesn't go up the three and find it, or maybe it can't find the property. I'm a bit confused by now because of all the different aliases (macroalias / property alias).

    What am i doing wrong?

     

     

  • MartinB 411 posts 512 karma points
    Aug 08, 2010 @ 22:43
    MartinB
    0

    If i use this method:

    <xsl:variable name="media" select="umbraco.library:GetMedia($currentPage/ancestor-or-self::node/data[@alias='bannerImage'], 0)/data" />

    then i can't manually override the default banner set on the container :/

  • Paul Blair 466 posts 731 karma points
    Aug 09, 2010 @ 02:17
    Paul Blair
    2

    You could try something like this:

    <xsl:variable name="imageSource" select="$currentPage/ancestor-or-self::* [string(bannerImage)!=''] [1]"></xsl:variable>

    This is using the new XSLT format for 4.5.

    How it works:

    Get all the nodes that meet your criteria from current page to the root. XSLT brings these back in order. The [1] specifies to select the 1st node closest to the $currentPage.

    Using the old format I think it would be something like:

    <xsl:variable name="imageSource" select="currentPage/ancestor-or-self::node/[string(data[@alias='bannerImage'])!=''] [1]/data[@alias='bannerImage']" />

    <xsl:variable name="media" select="umbraco.library:GetMedia($imageSource, 0)/data" />

    Cheers

    Paul

  • Matt Brailsford 4124 posts 22215 karma points MVP 9x c-trib
    Aug 09, 2010 @ 08:22
    Matt Brailsford
    1

    Hi martin

    you'll want to define a property on your macro to pass the value into, then rather than grabbing it from the current page, grab it from the macros properties instead

    Matt

  • MartinB 411 posts 512 karma points
    Aug 09, 2010 @ 08:51
    MartinB
    0

    Hi Matt and Paul

    Thanks for all your kind help.

    @Matt. Ok! that makes sense as to why i can't get it to work :-)

    Only one question remains (sorry). How do i add a macro property? :/

     

  • MartinB 411 posts 512 karma points
    Aug 09, 2010 @ 09:02
    MartinB
    0
  • Daniel Bardi 927 posts 2562 karma points
    Aug 09, 2010 @ 09:15
    Daniel Bardi
    1

    Macro property is a macro parameter.

    Define it in the macro UI under the Parameters tab.  Note the alias name you use.

    In your xslt do this:

    <xsl:param name="myparam" select="/macro/alias"/>

    ... where 'alias' in /macro/alias, is your alias in the macro parameter definition

    You can then use the value by reference with $myparam

    Hope this helps!

  • MartinB 411 posts 512 karma points
    Aug 09, 2010 @ 09:26
    MartinB
    0

    Ok, so my xslt would look like this then when i add the parameter?

    <xsl:param name="myparam" select="/macro/alias"/>

     <xsl:variable name="media" select="umbraco.library:GetMedia($currentPage/data[@alias='bannerImage'], 0)/data" />

        <xsl:if test="$media">
          <xsl:variable name="url" select="$media [@alias = 'umbracoFile']" />
          <xsl:variable name="width" select="$media [@alias = 'umbracoWidth']" />
          <xsl:variable name="height" select="$media [@alias = 'umbracoHeight']" />
          <img src="{$url}" width="{$width}" height="{$height}" />
        </xsl:if>

    How is that parameter telling umbraco to run recursively through my nodes? I mean, it's just a parameter with a value set by me. I can't see how that affects the rest of the XSLT ?

    Is it just how it is or? :-)

     

     

  • Matt Brailsford 4124 posts 22215 karma points MVP 9x c-trib
    Aug 09, 2010 @ 09:28
    Matt Brailsford
    0

    Hi Martin,

    Sorry, I did post a code sample with my last post, but it looks like the mobile site strips out your code (DOH!)

    Anyway, yea, as per Daniel said really, define your properties on the Paramters tab of the Macro edit interface, and then just request recall them as per Daniels example. One last thing to note, whatever you call "alias" in Daniels example, as also the attribute you need to define on your macro, so:

    <umbraco:macro alias="myMacro" myMacroPropertyAlias="[$myValue]" />

    Would require that you have a macro property defined with an alias of "myMacroPropertyAlias" which you would then retreive in your xslt as follows:

    <xsl:variable name="myProp" select="/macro/myMacroPropertyAlias" />

    Which you can then use the value of like so:

    <xsl:value-of select="$myProp" />

    or if it's a media item

    <xsl:value-of select="umbraco.library:GetMedia($myProp, '0')/umbracoFile

    Matt

  • MartinB 411 posts 512 karma points
    Aug 09, 2010 @ 09:44
    MartinB
    0

    Hi Matt

    Thanks for clarifying!

    If i create a macro parameter called "myMacroPropertyAlias" on the Parameters Tab then what would "myValue" be? As i can tell i have 3 fields when making a parameter.

    Alias - Name - Type (selectbox)

     

     

  • Matt Brailsford 4124 posts 22215 karma points MVP 9x c-trib
    Aug 09, 2010 @ 09:54
    Matt Brailsford
    0

    Hi Martin,

    "myValue" would be the property alias of the property defined on your doc type you want to pass through, so in your case it I belive it would be "bannerImage"

    Many thanks

    Matt

  • MartinB 411 posts 512 karma points
    Aug 09, 2010 @ 09:56
    MartinB
    0

    Hi Matt

    Just read your first reply where you answered that, sorry :)

    So when i add the parameter i shouldn't care about the fields "Name" and "Type", and just type in an alias, correct?

    I'm not at my workstation now, so obviously i would test it if i had the chance instead of keep asking. Hope it's alright, your help is very much appreciated!!

     

  • Matt Brailsford 4124 posts 22215 karma points MVP 9x c-trib
    Aug 09, 2010 @ 10:03
    Matt Brailsford
    0

    No problem,

    The type is some-what relevant, as you'll want to make sure the data types kinda match (I say kinda, as not all types are equivilant). If your macro is only ever going to be used in your template (and not be dropped in a ritch text editor), and the doc type property is of type mediaPicker, I'd be tempted to set the Type field to number, as mediaCurrent works sligtly differently to mediaPicker (mediaPicker returns the media items ID, mediaCurrent returns the actual media items XML).

    Name isn't that important, but just name it something relevant to your property "Banner Image"

    Matt

  • MartinB 411 posts 512 karma points
    Aug 09, 2010 @ 10:08
    MartinB
    0

    Actually it's going to sit firmly in the master template and is not meant for tinymce, so i'll stick with the number type (as it is a mediaPicker type)

    I'll give it a go later, hopefully with great succes ;-)

    Thanks alot thus far!

  • MartinB 411 posts 512 karma points
    Aug 09, 2010 @ 22:05
    MartinB
    0

    Hi again

    I'm totally bummed out by how little of this concept i am able to grasp.

    I've added the macro parameter, but i'm extremely confused about how my xslt should look.

    Right now i have this, not working by the way and i know it's wrong, it just gave up as i don't know what is up or down:

    <?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:param name="currentPage"/>

    <xsl:variable name="mediaId" select="/macro/mediaId"/>

    <xsl:variable name="myProp" select="/macro/myMacroPropertyAlias" />

    <xsl:template match="/">

    <xsl:value-of select="umbraco.library:GetMedia($myProp, '0')/umbracoFile

    <xsl:if test="$media &gt; 0">
    <xsl:variable name="mediaNode" select="umbraco.library:GetMedia($mediaId, 0)" />
    <xsl:if test="count($mediaNode/data) &gt; 0 and string($mediaNode/data[@alias='umbracoFile']) != ''">
    <img src="{$mediaNode/data[@alias='umbracoFile']}" alt="[image]" height="{$mediaNode/data[@alias='umbracoHeight']}" width="{$mediaNode/data[@alias='umbracoWidth']}" />
    </xsl:if>
    </xsl:if>

    </xsl:template>
    </xsl:stylesheet>
  • MartinB 411 posts 512 karma points
    Aug 09, 2010 @ 22:50
    MartinB
    0

    I think i have some trouble also with my toppage redirecting to its first child.

    Like:

    -SITE LANGUAGE SOMETHING CONTAINER

       - Frontpage

       - Page 2

       - Etc

    If i turn off the redirect, my initial xslt works for the frontpage and the next page shows a different image that i picked manually. The third page then breaks with an xslt parsing error.

    I really need that redirect :/

  • MartinB 411 posts 512 karma points
    Aug 09, 2010 @ 23:02
    MartinB
    0

    Ok this is insane.

    If i turn off redirecting, then i works like i would assume, except for one page. If i then alter something on that page and publish it, then it only shows the parent banner on all pages again.

    If i then go back and set redirect back on, i works again, except for one page until i publish something.

    I have no clue about what the hell is going on here :/ ?

     

    xslt:

    <?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:param name="currentPage"/>

    <xsl:template match="/">

    <textarea>
    <xsl:value-of select="$currentPage/ancestor-or-self::node/data[@alias='bannerImageLeft']"/>
    </textarea>

    <xsl:if test="$currentPage/ancestor-or-self::node/data[@alias='bannerImageLeft'] != ''">
    <img alt="{$currentPage/@nodeName}">
    <xsl:attribute name="src">

    <xsl:value-of select="umbraco.library:GetMedia($currentPage/ancestor-or-self::node/data[@alias='bannerImageLeft'], 'false')/data[@alias = 'umbracoFile']" />

    </xsl:attribute>
    </img>
    </xsl:if>

    </xsl:template>
    </xsl:stylesheet>
  • MartinB 411 posts 512 karma points
    Aug 09, 2010 @ 23:06
    MartinB
    0

    Erh...

    Now i deleted the one page with the parsing error on it, and now it seems to work??

    Anyone ever tried something like this?

  • MartinB 411 posts 512 karma points
    Aug 09, 2010 @ 23:12
    MartinB
    0

    This must be some sort of 4.0.2 -> 4.5.1 upgrade thing and i use the old schema.

    Everytime i make a new node and sort it, my recursive function stops working. If i delete the new page and reublish my frontpage, then it works again.

  • MartinB 411 posts 512 karma points
    Aug 09, 2010 @ 23:21
    MartinB
    0

    debug gives me this:

    Value was either too large or too small for an Int32.
    Value was either too large or too small for an Int32.
      at System.Convert.ToInt32(Double value)
      at System.Double.System.IConvertible.ToInt32(IFormatProvider provider)
      at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
      at System.Xml.Xsl.Runtime.XmlQueryRuntime.ChangeTypeXsltArgument(XmlQueryType xmlType, Object value, Type destinationType)
      at System.Xml.Xsl.Runtime.XmlQueryContext.InvokeXsltLateBoundFunction(String name, String namespaceUri, IList`1[] args)
      at System.Xml.Xsl.CompiledQuery.Query.<xsl:template match="/">(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime, XPathNavigator {urn:schemas-microsoft-com:xslt-debug}current, Double {urn:schemas-microsoft-com:xslt-debug}position, Double {urn:schemas-microsoft-com:xslt-debug}last, IList`1 {urn:schemas-microsoft-com:xslt-debug}namespaces) in C:\Inetpub\wwwroot\moderndrums2\xslt\bannerImageLeft.xslt:line 18
      at System.Xml.Xsl.CompiledQuery.Query.<xsl:apply-templates>(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime, XPathNavigator , Double , Double )
      at System.Xml.Xsl.CompiledQuery.Query.Root(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime)
      at System.Xml.Xsl.CompiledQuery.Query.Execute(XmlQueryRuntime {urn:schemas-microsoft-com:xslt-debug}runtime)
      at System.Xml.Xsl.XmlILCommand.Execute(Object defaultDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlSequenceWriter results)
      at System.Xml.Xsl.XmlILCommand.Execute(Object defaultDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlWriter writer, Boolean closeWriter)
      at System.Xml.Xsl.XmlILCommand.Execute(IXPathNavigable contextDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlWriter results)
      at System.Xml.Xsl.XmlILCommand.Execute(IXPathNavigable contextDocument, XmlResolver dataSources, XsltArgumentList argumentList, TextWriter results)
      at System.Xml.Xsl.XslCompiledTransform.Transform(IXPathNavigable input, XsltArgumentList arguments, TextWriter results)
      at umbraco.macro.GetXsltTransformResult(XmlDocument macroXML, XslCompiledTransform xslt, Dictionary`2 parameters)
      at umbraco.macro.GetXsltTransformResult(XmlDocument macroXML, XslCompiledTransform xslt)
      at umbraco.macro.loadMacroXSLT(macro macro, Hashtable attributes, Hashtable pageElements)

  • MartinB 411 posts 512 karma points
    Aug 11, 2010 @ 16:23
    MartinB
    0

    This error is quite common it seems BUT

    I can't believe why i didn't just think of using an umbraco item running a richtext editor, in which i can easily insert an image/banner and assign a link to it. And just as easily make it recursive.

    God damnit :-)

    Thanks to all who tried to help out.

     

Please Sign in or register to post replies

Write your reply to:

Draft