Copied to clipboard

Flag this post as spam?

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


  • Jon R. Humphrey 164 posts 455 karma points c-trib
    Aug 11, 2011 @ 04:33
    Jon R. Humphrey
    0

    Redirect to nth child node in Razor?

    What is the best practice to redirect from a parent node to the nth child node instead of using 'umbracoRedirect' to redirect to the specific page? The site structure is setup like this:

    • homepage
      • Category 1
        • Project 1
          • Gallery 1
            • SubGallery 1
            • SubGallery 2
          • Gallery 2
          • Gallery 3
            • SubGallery X
        • Project #
          • Gallery #
      • Category 2
        • Project A
          • Gallery A
        • Project #
          • Gallery #
      • Textpage

    So, when you are on the homepage and click on Category 1, this actually takes you to SubGallery 1; but if you click on Gallery 2, this would take you right there; or, if you clicked on Gallery 3, this would take you to SubGallery X? I think this would be a type of deeplinking but I've not done that before so I'm probably wrong?

    I've already done this with xslt from the link below, but only to the first child and would now like to use Razor and link deeper? [  http://our.umbraco.org/forum/developers/xslt/2834-Redirect-to-first-child-node-in-xslt?p=0 ]

    If anyone would like to point me in the right direction I would be eternally grateful!

    Here is my code at the moment:

    @inherits umbraco.MacroEngines.DynamicNodeContext
    @{
    dynamic projects = @Model.Descendants("stfuProjectpage").Where("ChildrenAsList.Count > 0").FirstOrDefault();

    if(projects != null) {
    <nav id="top_nav">
    <a class="hidden" href="#main" title="Skip to content">Skip to Content</a>
    <ul class="horizontal piped">
    @foreach (var gallery in projects) {
    var selected = Array.IndexOf(@Model.Path.Split(','), @gallery.Id.ToString()) >= 0 ? "navigation selected" : "navigation";
    <li><a class="@selected" href="@gallery.Url">@gallery.Name</a></li>
    }
    </ul>
    </nav>
    }
    }

     

    Thanks in advance!

     

  • Jon R. Humphrey 164 posts 455 karma points c-trib
    Aug 11, 2011 @ 04:42
    Jon R. Humphrey
    0

    Forgot to add the code for the sub-nav which also need to be able to jump to the nth child:

    @inherits umbraco.MacroEngines.DynamicNodeContext
    @{
      var level = String.IsNullOrEmpty(Parameter.Level) ? 1 : int.Parse(Parameter.Level);
      var controlId = String.IsNullOrEmpty(Parameter.ControlId) ? "navigation_control" : Parameter.ControlId;
      var parent = @Model.AncestorOrSelf(level);
      if (parent != null) {
        <ul id="@controlId" class="horizontal piped">
        @foreach (var item in parent.stfuProjectGallery.Where("Visible")) {
          var selected = Array.IndexOf(Model.Path.Split(','), item.Id.ToString()) >= 0 ? "navigation selected" : "navigation";
          <li><a class="@selected" href="@item.Url">@item.Name</a></li>
          }
        </ul>
      }
    }

    Sorry if this confuses the issue any further!

  • Dan Diplo 1554 posts 6205 karma points MVP 6x c-trib
    Aug 12, 2011 @ 16:40
    Dan Diplo
    1

    I might have got the wrong idea about what you are trying to do. But if what you want is to redirect to the last leaf node of the current node (ie. the last descendant node in the tree) then this should do it:

    @inherits umbraco.MacroEngines.DynamicNodeContext
    
    @{
        var last = Model.DescendantsOrSelf().Last();
    
        if (last != null && Model.Id != last.Id)
        {
            Response.Redirect(last.Url);
        }
    }
  • Jon R. Humphrey 164 posts 455 karma points c-trib
    Aug 12, 2011 @ 19:40
    Jon R. Humphrey
    0

    Dan,

    First thanks for this, I didn't know about the "last()"!
    I've now tried this and this takes me too deep: to the first image of the last gallery...

    Second, upon closer examination of the initial post I realised I don't think I explained as best I could! Doh!

    Let me 'splain again:

    • The homepage has a thumbnail gallery which currently links to the respective project;
    • A project will always have at least one gallery, but could have up to three;
    • A gallery could have up to three sub-galleries below it;

    User Journey:

    1. The user clicks the homepage thumbnail and is should be taken to the first gallery
    2. If that gallery has a sub-gallery then they would be taken to that instead
    3. The user can then move to another gallery via the gallery navigation menu
    4. If that gallery has a sub-gallery then they would be taken there instead
    5. The user can then move between any sub or prime galleries via the respective menu

    Maybe this will help understand what's supposed to happen better!
    *Note to self: Don't post late at night anymore!

    If you would like to see something more concrete, let me know and I'll send you a link to my development server.

    Cheers for any and all help with this!

  • Dan Diplo 1554 posts 6205 karma points MVP 6x c-trib
    Aug 15, 2011 @ 11:25
    Dan Diplo
    0

    If you just want to jump to the last gallery then you should be able to use this (assuming your gallery alias is Gallery):

     var last = Model.DescendantsOrSelf("Gallery").Last();

     

  • Jon R. Humphrey 164 posts 455 karma points c-trib
    Aug 15, 2011 @ 12:33
    Jon R. Humphrey
    0

    Cheers for this one too Dan, sadly it's not the last gallery but the first?

    I was able to get the top navigation to work, which is done currently in XSLT, by using

    ./*/*[@isDoc]"

    As you can see in the code snippet below:

      <ul class="horizontal piped">
        <xsl:for-each select="$currentPage/ancestor-or-self::* [@level=$level]/* [@isDoc and string(umbracoNaviHide) != '1']">
        <li>
          <a>
            <xsl:attribute name="href">
              <xsl:choose>
                <xsl:when test="count(./*/*[@isDoc]) > 0">
                  <xsl:value-of select="umbraco.library:NiceUrl(./*/*[@isDoc]/@id)" />
                xsl:when>
                <xsl:otherwise>
                  <xsl:value-of select="umbraco.library:NiceUrl(@id)" />
                xsl:otherwise>
              xsl:choose>
            xsl:attribute>

            <xsl:attribute name="class">
              <xsl:value-of select="concat('navItem',position() + number(0))" />
              <xsl:if test="$currentPage/ancestor-or-self::*[@isDoc]/@id = @id">
                <xsl:text> selectedxsl:text>
              xsl:if>
            xsl:attribute>                      
          <xsl:value-of select="@nodeName" />
          a>
        li>
        xsl:for-each>
      ul>

    But as the homepage thumbnail gallery is created with Razor I need to place this same functionality in there:

    @using System.Xml
    @using System.Xml.Linq
    @using umbraco.MacroEngines

    @functions {
      public static string GetImageCropperUrlFullMedia(string mediaXml, string cropName) {
        string cropUrl = string.Empty;
      
        XmlDocument xmlDocument = new XmlDocument();
        xmlDocument.LoadXml("" + mediaXml + "");
        XmlNode cropNode = xmlDocument.SelectSingleNode("descendant::crops/crop[@name='"+ cropName +"']");
     
        if (cropNode != null){
          cropUrl = cropNode.Attributes.GetNamedItem("url").InnerText;
        }
        return cropUrl;
      }
    }


      <ol id="project_items" class="noBullet horizontal">
      @foreach ( dynamic project in Model.Descendants().Where( "umbracoNaviHide != true" ) ) {
        var thumb = String.Empty;

        if ( project.GetProperty( "projectThumbnailImage" ) != null && project.GetProperty( "projectThumbnailImage" ).Value != "" ) {
          thumb = GetImageCropperUrlFullMedia( @project.GetProperty( "projectThumbnailImage" ).Value.ToString(), "GalleryImageThumbnail" );
        } else {
          thumb = "/css/global/no_image_found.png";
        }

        if ( @project.Parent.Name == "CategoryName" ) {
          <li>
            <header>
              <h6>
                <a href="@project.Url">
                  <img src="@thumb" alt="@project.projectTitle" />
                  <span>@project.projectTitle - @project.ProjectDate.ToString("yyyy")</span>
                </a>
              </h6>
            </header>
          <article>
            <p>@project.shortDescription</p>@*<p role="button"><a href="@project.Url">[more]</a></p>*@
          </article>
          </li>
        }
      }
      </ol>

    Thanks for all your help by the way!

    Jon

  • Dan Diplo 1554 posts 6205 karma points MVP 6x c-trib
    Aug 15, 2011 @ 13:45
    Dan Diplo
    0

    I'm probably not quite understanding (not your fault) but it sounds like you want to find the first descendant page that is a Gallery and then, from there, the last descendant Gallery? So, I think you could do it in two steps.

    1)  var firstGallery = Model.DescendantsOrSelf("Gallery").First();

    2) var gallery = firstGallery.DescednantsOrSelf("Gallery").Last();

    It's hard to test, but those are my thoughts!

  • Jon R. Humphrey 164 posts 455 karma points c-trib
    Aug 15, 2011 @ 17:07
    Jon R. Humphrey
    0

    DAN!!!!!

    We're so bloody close I can smell the coffee!!!!!

    Here's my adjustments based on your recommendations:

    @using System.Xml
    @using System.Xml.Linq
    @using umbraco.MacroEngines

    @functions {
      public static string GetImageCropperUrlFullMedia(string mediaXml, string cropName) {
        string cropUrl = string.Empty;
      
        XmlDocument xmlDocument = new XmlDocument();
        xmlDocument.LoadXml("" + mediaXml + "");
        XmlNode cropNode = xmlDocument.SelectSingleNode("descendant::crops/crop[@name='"+ cropName +"']");
     
        if (cropNode != null){
          cropUrl = cropNode.Attributes.GetNamedItem("url").InnerText;
        }
        return cropUrl;
      }
    }


      <ol id="project_items" class="noBullet horizontal">
      @foreach ( dynamic project in Model.Descendants().Where( "umbracoNaviHide != true" ) ) {
                                                                                              
        var firstGallery = @project.DescendantsOrSelf("stfuGallery").First();
        var thumb = String.Empty;

        var link = ( @firstGallery != null ) ? @firstGallery.Url : @project.Url;

        if ( project.GetProperty( "projectThumbnailImage" ) != null && project.GetProperty( "projectThumbnailImage" ).Value != "" ) {
          thumb = GetImageCropperUrlFullMedia( @project.GetProperty( "projectThumbnailImage" ).Value.ToString(), "GalleryImageThumbnail" );
        } else {
          thumb = "/css/global/no_image_found.png";
        }

        if ( @project.Parent.Name == "Architecture" ) {
          <li>
            <header>
              <h6>
                  <a href="@link">
                  <img src="@thumb" alt="@project.projectTitle" />
                  <span>@project.projectTitle - @project.ProjectDate.ToString("yyyy")</span>
                </a>
              </h6>
            </header>
          <article>
            <p>@project.shortDescription</p>@*<p role="button"><a href="@project.Url">[more]</a></p>*@
          </article>
          </li>
        }
      }
      </ol>

    WHICH WORKS!!!!!!!!

    YAYYYYYYY!!!!!

    Thank you thank you thank you thank you thank you!
    J

  • Dan Diplo 1554 posts 6205 karma points MVP 6x c-trib
    Aug 15, 2011 @ 20:55
    Dan Diplo
    0

    Excellent! Very pleased to be of some assistance. Good luck with the rest of your project!

  • Jon R. Humphrey 164 posts 455 karma points c-trib
    Aug 15, 2011 @ 23:01
    Jon R. Humphrey
    0

    Dan,

    Thanks to you I also solved the sub-nav issue as well!

    First though, the "gallery.DescendantsOrSelf("nodeTypeAlias").First()" was not working it was either throwing an error or just wouldn't return the grandchild at all? So, I went back into the post by Gareth Evans [http://umbraco.com/follow-us/blog-archive/2011/3/13/umbraco-razor-feature-walkthrough-part-5] and did a little refactoring to come up with this, which works:

    @inherits umbraco.MacroEngines.DynamicNodeContext
    @{
      var level = String.IsNullOrEmpty(Parameter.Level) ? 1 : int.Parse(Parameter.Level);

      var parent = @Model.AncestorOrSelf( level );
      if (parent != null) {
      <ul class="horizontal piped">
      @foreach (dynamic gallery in @parent.stfuGallery.Where("Visible")) {

        var firstGallery = @gallery.Down("stfuGallery");
        var link = ( @firstGallery != null ) ? @firstGallery.Url : @gallery.Url;
                                                                           
        var selected = Array.IndexOf(Model.Path.Split(','), gallery.Id.ToString()) >= 0 ? "navigation selected" : "navigation";
        
        <li><a class="@selected" href="@link">@gallery.Name</a></li>
        }
      </ul>
      }
    }

    Do you see anything wrong with this or a better way to go to the first grandchild of the project?

    Thanks for all your help with this and I hope the karma comes right back for ya, let me know if I can return the favour!

    J

  • Dan Diplo 1554 posts 6205 karma points MVP 6x c-trib
    Aug 16, 2011 @ 12:16
    Dan Diplo
    0

    Hi! I'm not sure why First() doesn't work for you, as I've tried it my self in some simple examples and it seems to work. But I don't know the Umbraco internals, so there may be circumstances (perhaps with nulls or something) that screw it up. But it seems you have a clever work-around using Down(). The only thing to beware of is that (according to docs) "If a node doesn't match the requested node, you'll get null - so look out for null references." So you might want to check that firstGallery isn't null before referencing it.

    Anyway, glad to have been of some small help!

Please Sign in or register to post replies

Write your reply to:

Draft