Copied to clipboard

Flag this post as spam?

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


  • Dennis M Dewey 15 posts 35 karma points
    Oct 29, 2011 @ 06:23
    Dennis M Dewey
    0

    Dropdown menu with different classes based on level

    Hello everyone! This is my first post on a CMS I just started using for a client. What happened was that they hired someone to design a site for them in Umbraco but he made mostly everything static (because he obviously didn't know what he was doing) and they've asked me to make it all dynamic - and I don't really know what I'm doing when it comes to Umbraco. I only have had experience with Wordpress and Movable Type for the most part so I'm having to learn as I go along.

    Umbraco seems to be pretty flexible. I'm more of a designer so XSLT is very foreign and I think that it would be better if I tried to do everything using razor instead. Well, I have this code I'm trying to generate using razor, but I don't honestly know the first place to start.

    <div class="menu">

    <ul>

    <li><a href="#url">Company</a></li>

    <li class="hasSub"><a href="#url">Products</a>

    <ul>

    <li><a class="fly" href="#url">Mobile Audio</a>

    <ul>

    <li><a class="fly" href="#url">Woofers</a>

    <ul>

    <li><a href="#url">500</a></li>

    </ul>

    </li>

    <li><a href="#url">Components</a></li>

    </ul>

    </li>

    </ul>

    </li>

    <li class="hasSub"><a href="#url">Dealers</a>

    <ul>

    <li><a href="#url">Find a Dealer</a></li>

    <li><a href="#url">Become a U.S. Dealer</a></li>

    </ul>

    </li>

    </ul>

    </div>

    This is a menu that has needs a class assigned to the parent url if it has children and then a different class needs to be assigned if the parent of a submenu is greater than 1 level deep.

  • Dennis M Dewey 15 posts 35 karma points
    Oct 29, 2011 @ 06:50
    Dennis M Dewey
    0

    Of course I've already seen this pre-canned version from Umbraco's templates :

    @inherits umbraco.MacroEngines.DynamicNodeContext
    @{ 
        var level = String.IsNullOrEmpty(Parameter.Level) ? 1 : int.Parse(Parameter.Level); 
        var ulClass = String.IsNullOrEmpty(Parameter.UlClass) ? "" : String.Format(" class=\"{0}\"", Parameter.UlClass); 
        var parent = @Model.AncestorOrSelf(level);
        if (parent != null) {
            <[email protected](ulClass)>
            @foreach (var item in parent.Children.Where("Visible")) {
                var selected = Array.IndexOf(Model.Path.Split(','), item.Id.ToString()) >= 0 ? " class=\"selected\"" : "";
                <[email protected](selected)>
                    <a href="@item.Url">@item.Name</a>
                </li>
                }
            </ul>
        }
    }
    
    

    btw... I'm using Umbraco 4.7 - I still haven't upgraded to 4.7.1 yet, but I wanted to see if I could get it to work on 4.7 right now because the client hasn't upgraded yet either.

  • Rich Green 2246 posts 4008 karma points
    Oct 29, 2011 @ 10:30
    Rich Green
    0

    Hey Dennis,

    If you're using Razor I would push them to upgrade to 4.7.1.

    I would then have a look at the Razor site map template that comes out the box in Umbraco.

    Also I would have a look at this package (it does mean installing Umbraco and then installing the package) http://our.umbraco.org/projects/developer-tools/cultiv-razor-examples

    Also if you can I would post an image of your content tree so we can see your structure. 

    Hope that helps

    Rich

  • Dennis M Dewey 15 posts 35 karma points
    Oct 29, 2011 @ 23:25
    Dennis M Dewey
    0

    Thanks Rich,

    I have looked at that Cultiv Razor Examples and played around with it a bit. I also checked out the sitemap, but still don't know how to test for and output a different class based on the level. I will try to play around with it some more. I think that I'll probably have to use the sitemap as a starting point.The structure of the site is going to be something like below. It's not how exactly it is right now, but I'm changing it to this (the other designer didn't organize very well) :

    - | Home
    - | Company
    - | Mobile Products
    - - | Woofers
    - - - | Model 500 series
    - - | Components
    - | Dealers
    - - | Find a Dealer
    - - | Become a U.S. Dealer

    I there a big difference between 4.7 and 4.7.1 regarding the functionality of razor?

  • Dennis M Dewey 15 posts 35 karma points
    Oct 30, 2011 @ 02:12
    Dennis M Dewey
    0

    I figured out part of it. I just need to try to test for the level now :

     

    @helper traverse(dynamic node){
      var maxLevelForSitemap = 4;
    
      var values = new Dictionary<string,object>();
      values.Add("maxLevelForSitemap", maxLevelForSitemap) ;
    
       var items = node.Children.Where("Visible && Level <= maxLevelForSitemap", values);
       <ul>
                @foreach (var item in items) {
                var hasChildren = false;
                if (item.Children.Count() > 1) {
                hasChildren = true;
                }
                    <li><a href="@item.Url" class="@(hasChildren ? "fly" : "nochild")">@item.Name</a>
        @traverse(item)
                    </li>
                }
       </ul>
    }
    <div id="sitemap"> 
        @traverse(@Model.AncestorOrSelf())
    </div>
    
  • Dennis M Dewey 15 posts 35 karma points
    Oct 30, 2011 @ 03:14
    Dennis M Dewey
    0

    Unfortunately, this is not working correctly.

    @helper traverse(dynamic node){
      var maxLevelForSitemap = 4;
    
      var values = new Dictionary<string,object>();
      values.Add("maxLevelForSitemap", maxLevelForSitemap) ;
    
       var items = node.Children.Where("Visible && Level <= maxLevelForSitemap", values);
       <ul>
                @foreach (var item in items) {
                var hasChildren = "zero";
                if (item.Level() >= 1 && item.Children.Count() > 1) {
                hasChildren = "one";
                } else if (item.Level() >= 2 && item.Children.Count() > 1) {
                hasChildren = "two";
                } else {
                hasChildren = "zero";
                }
                    <li><a href="@item.Url" class="@hasChildren">@item.Name</a>
        @traverse(item)
                    </li>
                }
       </ul>
    }
    <div id="sitemap"> 
        @traverse(@Model.AncestorOrSelf())
    </div>
    

    I probably have the logic incorrect. Anyway, I have a stylesheet that looks like this

    a.zero {color:#cccccc}
    a.one {color:#000000}
    a.two {color:#808080}
    

    This is what the output is looking like :

    This is what the output needs to look like :

     

    I hope that makes sense. Any ideas?

  • Jan Skovgaard 11280 posts 23678 karma points MVP 10x admin c-trib
    Oct 30, 2011 @ 03:41
    Jan Skovgaard
    0

    Hi Dennis

    I know this answer does not tell you how to place write the classes mentioned on the elements with Razor, but I'm thinking that you might be able to benefit from using the :nth-child() selector in CSS3 to set the classes perhaps? And if you need a fallback for older browsers you could use the :nth-child selector with jquery instead for instance?

    Just a thought...

    /Jan

  • Dennis M Dewey 15 posts 35 karma points
    Oct 30, 2011 @ 04:00
    Dennis M Dewey
    0

    Thanks for the input Jan,

    I actually have thought of that (the jquery method), but want to use it as a last resort because I'm stubborn and don't want to have to rely on jquery. The CSS3 method is not an option because it needs to support ie7.

    What I'm probably going to have to do is make the site navigation less complicated for now and just have separate submenus until I figure this out.

  • Dennis M Dewey 15 posts 35 karma points
    Oct 30, 2011 @ 07:23
    Dennis M Dewey
    0

    I figured it out. It works with this menu by Stu Nicholls at cssplay :

     http://www.cssplay.co.uk/menus/iPad-Anywidth3.html

    here is the code. I am sure it probably could be optimized. I simplified above to avoid confusion.

    @helper traverse(dynamic node){
      var maxLevelForSitemap = 4;
    
      var values = new Dictionary<string,object>();
      values.Add("maxLevelForSitemap", maxLevelForSitemap) ;
    
       var items = node.Children.Where("Visible && Level <= maxLevelForSitemap", values);
       <ul>
                @foreach (var item in items) {
                var linkItemIsParent = "noFly";
                if (item.Level() > 2 && item.Children.Count() >= 1) {
                linkItemIsParent = "fly";
                } 
                var listItemIsParent = "hasNoSub";
                if (item.Level() == 2 && item.Children.Count() >= 1) {
                listItemIsParent = "hasSub";
                } 
                    <li class="@listItemIsParent"><a href="@item.Url" class="@linkItemIsParent">@item.Name</a>
        @traverse(item)
                    </li>
                }
       </ul>
    }
    <div class="menu"> 
        @traverse(@Model.AncestorOrSelf())
    </div>
    
    
    
    
  • Rich Green 2246 posts 4008 karma points
    Oct 30, 2011 @ 08:45
    Rich Green
    0

    Hey Dennis,

    Nice one, glad you got it worked out :)

    Rich

  • Dennis M Dewey 15 posts 35 karma points
    Nov 01, 2011 @ 01:39
    Dennis M Dewey
    0

    I improved it by getting rid of the empty ul tags that were being generated.

    @inherits umbraco.MacroEngines.DynamicNodeContext
    
    @helper traverse(dynamic node){
    var maxLevelForSitemap = 99;
    
    var values = new Dictionary<string,object>();
    values.Add("maxLevelForSitemap", maxLevelForSitemap) ;
    
       var items = node.Children.Where("template!=0").Where("Visible").Where("Level <= maxLevelForSitemap", values);
       if (items.Count() > 0) { 
       <ul>
                @foreach (var item in items) {
                var linkItemIsParent = "noFly";
                if (item.Level() > 2 && item.Children.Count() >= 1) {
                linkItemIsParent = "fly";
                } 
                var listItemIsParent = "hasNoSub";
                if (item.Level() == 2 && item.Children.Count() >= 1) {
                listItemIsParent = "hasSub";
                } 
                    <li class="@listItemIsParent"><a href="@item.Url" class="@linkItemIsParent">@item.Name</a>
        @traverse(item)
                    </li>
                }
       </ul>
       }
    }
    <div class="menu"> 
        @traverse(@Model.AncestorOrSelf())
    </div>
    

    This post helped with that : http://our.umbraco.org/forum/developers/razor/18637-Fix-for-Razor-Sitemap-html-error-empty-ul-tags

  • marmar 35 posts 28 karma points
    Feb 13, 2012 @ 00:25
    marmar
    0

    When trying this code out, and getting it to run (just to test it to learn how to use this type of recursive structure, i get the following error:

    Error loading Razor Script temp.cshtml

    Incorrect number of parameters supplied for lambda declaration

    Any ideas why this would be happening? I am running 4.7

    @helper traverse(dynamic node){
     
    var maxLevelForSitemap =4;

     
    var values =newDictionary<string,object>();
      values
    .Add("maxLevelForSitemap", maxLevelForSitemap);

       
    var items = node.Children.Where("Visible && Level <= maxLevelForSitemap", values);
       
    <ul>
               
    @foreach(var item in items){
               
    var linkItemIsParent ="noFly";
               
    if(item.Level()>2&& item.Children.Count()>=1){
                linkItemIsParent
    ="fly";
               
    }
               
    var listItemIsParent ="hasNoSub";
               
    if(item.Level()==2&& item.Children.Count()>=1){
                listItemIsParent
    ="hasSub";
               
    }
                   
    <li class="@listItemIsParent"><a href="@item.Url"class="@linkItemIsParent">@item.Name</a>
        @traverse(item)
                    </
    li>
               
    }
       
    </ul>
    }
    <div class="menu">
        @traverse(@Model.AncestorOrSelf())
    </
    div>

Please Sign in or register to post replies

Write your reply to:

Draft