10 posts by 3 authors in: Forums > CMS Builder
Last Post: September 28, 2017   (RSS)

By terryally - September 10, 2017 - edited: September 10, 2017

Hi,

I need to add the following classes highligted in red to a CMSB generated category menu when the level 1 item has a child and span tags when the item irrespective of level has a children/children. How do I accomplish this?

                <ul class="nav sf-menu clearfix">
                    <li class="active sub-menu"><a href="index.html">Home</a><span></span>
                        <ul class="submenu">
                            <li><a href="#">Lorem ipsum dolor sit<span></span></a>
                              <ul class="submenu">
                                    <li><a href="#">Lorem ipsum dolor sit</a></li>
                                    <li><a href="#">Conse ctetur adipisicing</a></li>
                                    <li><a href="#">Elit sed do eiusmod tempor</a></li>
                                    <li><a href="#">Incididunt ut labore</a></li>
                                    <li><a href="#">Et dolore magna aliqua</a></li>
                              </ul>  
                            </li>
                            <li><a href="#">Conse ctetur adipisicing</a></li>
                            <li><a href="#">Elit sed do eiusmod tempor</a></li>
                            <li><a href="#">Incididunt ut labore</a></li>
                            <li><a href="#">Et dolore magna aliqua</a></li>
                        </ul>
                    </li>
                    <li><a href="index-1.html">About</a></li>
                    <li><a href="index-2.html">Blog</a></li>
                    <li><a href="index-3.html">Gallery</a></li>
                    <li><a href="index-4.html">Contacts</a></li>
                </ul>

  // load records from 'navigation_menu'
  list($navigation_menuRecords, $selectedNavigation_menu) = getCategories(array(
    'tableName'            => 'navigation_menu', //
    'categoryFormat'       => 'showall',  // showall, onelevel, twolevel, breadcrumb
    'defaultCategory'      => 'first',    // Enter 'first', a category number, or leave blank '' for none
    
    // advanced options (you can safely ignore these)
    'rootCategoryNum'      => '',      // Only categories _below_ this one will be shown (defaults to blank or 0 for all)
    'ulAttributes'         => 'class="submenu"',      // add html attributes to <ul> tags, eg: 'class="menuUL"' would output <ul class="menuUL">
    'selectedCategoryNum'  => '',      // this record number is returned as the "selected category", defaults to getLastNumberInUrl()
    'ulAttributesCallback' => '',      // ADVANCED: custom function to return ul attributes, eg: 'myUlAttr' and function myUlAttr($category) { return "id='ul_uniqueId_{$category['num']}'"; }
    'liAttributesCallback' => '',      // ADVANCED: custom function to return li attributes, eg: 'myLiAttr' and function myLiAttr($category) { return "id='li_uniqueId_{$category['num']}'"; }
    'loadCreatedBy'        => false,   // loads createdBy.* fields for user who created category record (false is faster)
    'loadUploads'          => true,    // loads upload fields, eg: $category['photos'] gets defined with array of uploads (false is faster)
    'ignoreHidden'         => false,   // false = hide records with 'hidden' flag set, true = ignore status of hidden flag when loading records
    'debugSql'             => false,   // display the MySQL query being used to load records (for debugging)
  ));

Thanks

Terry

By Zicky - September 11, 2017 - edited: September 11, 2017

Hey Terry,

I've been looking this over off and on since you posted this. I've accomplished similar needs in the past using jQuery addClass to nested <ul> and <li>... very similar to what you're trying. The biggest challenge I see is triggering the addClass function to a nested <li> once the parent <li> has been triggered.

I'm sorry to say I don't have a solution, but you may want to check out this post on stackoverflow. It covers a similar need such as yours which I think may fit your need, or you may find useful... and if I get this figured out I'll post up what I come up with.

https://stackoverflow.com/questions/8534603/jquery-to-dynamically-add-classes-to-a-nested-list-item-to-flag-menus-that-have

Hey Terry,

I dug up some code from a menu I worked on a few years back. I modified it a bit to get it close to what you need. There will still be the need for some modification on your part to get it where you need it to function, but it does apply the different classes based on selections. Hopefully you'll be able to use this. If you modify it to a new solution, please share what you come up with... maybe I and others could use what you come up with as well.

<?php
  /* STEP 1: LOAD RECORDS - Copy this PHP code block near the TOP of your page */

  // load viewer library
  $libraryPath = 'cmsb/lib/viewer_functions.php';
  $dirsToCheck = array('/home/directory/domain.com/','','../','../../','../../../');
  foreach ($dirsToCheck as $dir) { if (@include_once("$dir$libraryPath")) { break; }}
  if (!function_exists('getRecords')) { die("Couldn't load viewer library, check filepath in sourcecode."); }
  
   // load records
  list($navigation_menuRecords, $navigation_menuMetaData) = getCategories(array(
    'tableName'   => 'navigation_menu',
    'categoryFormat' => 'showall',
  ));

?>
<?php 
   $subMenuLinks   = ""; 
   foreach ($navigation_menuRecords as $menuCategory) {      
   if ($menuCategory['_isSelected'] || $menuCategory['_isParentSelected'] || $menuCategory['_isChildSelected']) {        
      $subMenuLinks[] = $menuCategory;     
      } 
   }  
?>

<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Categories</title>

<style type="text/css">
ul {
    list-style:none;
    margin:0;
    padding:0; 
}
li {
    width:22%;
    float:left;
    display:block;
    padding:1em;
    text-align:center;
    border:#555 solid 1px;
}
li a:hover {
    background:#eaeaea;
}
.submenu li {
    background:#ccc;
}
</style>

</head>

<body>


<ul class="nav sf-menu clearfix">

<?php $selectedCat="2"; ?>
<?php foreach($navigation_menuRecords as $category):?>  
  <?php if(!$category['_hasParent']):?>  
      <?php /*?><?php echo $category['_listItemStart']; ?><?php */?>  
       <?php if($category['_isSelected']){ echo "<li class='active sub-menu'>"; $selectedCat=$category['num']; } else { echo "<li>"; } ?>
         <a href="?category=<?php echo $category['num']?>"><?php echo $category['name']; ?></a>
       <?php if($category['_isSelected']){ echo "<span>Trigger 1st Span</span></li>"; } else { echo "</li>"; } ?>
      <?php /*?><?php echo $category['_listItemEnd']; ?><?php */?>  
   <?php endif ?>  
<?php endforeach ?>
 
<?php if($selectedCat): ?>
<ul class="submenu">
    <?php foreach($navigation_menuRecords as $category): ?>  
      <?php if ($selectedCat==$category['parentNum']):?> 
          <?php /*?><?php echo $category['_listItemStart']; ?><?php */?> 
           <?php $selectedSubCat=$category['num']; ?> 
            <li><a href="?subCat=<?php echo $category['num'];?>&category=<?php echo $selectedCat;?>"><?php echo $category['name'] ?><span>Trigger 2nd Span</span></a></li>
          <?php /*?><?php echo $category['_listItemEnd']; ?><?php */?>  
      <?php endif ?>  
    <?php endforeach ?>
</ul>
<?php endif ?>

<?php if(@$_REQUEST['subCat']): ?> 
<ul class="submenu">
   <?php foreach($navigation_menuRecords as $category): ?>  
     <?php if ($_REQUEST['subCat']==$category['parentNum']):?> 
        <?php /*?><?php echo $category['_listItemStart']; ?><?php */?> 
          <?php $selectedSubCat=$category['num']; ?> 
           <li><a href="<?php echo $category['_link'] ?>"><?php echo $category['name'] ?></a></li>
         <?php /*?><?php echo $category['_listItemEnd']; ?><?php */?>  
     <?php endif ?>  
   <?php endforeach ?> 
</ul> 
<?php endif ?>

</ul>


</body>
</html>

Zicky

Hi Zicky,

I appreciate your assistance. I will experiment with this and let you know.

Regards

Terry

Hey Zicky,

I got this sorted last night and here is how I achieved it ... first by using two of the advanced options to insert classes into the nested <ul> tags and into the <li> tags which have submenu items.

 // load records from 'navigation_menu'
  list($navigation_menuRecords, $selectedNavigation_menu) = getCategories(array(
    'tableName'            => 'navigation_menu', //
    'categoryFormat'       => 'showall',  // showall, onelevel, twolevel, breadcrumb
    'defaultCategory'      => 'first',    // Enter 'first', a category number, or leave blank '' for none
    
    // advanced options (you can safely ignore these)
    'ulAttributes'         => 'class="submenu"',      // add html attributes to <ul> tags, eg: 'class="menuUL"' would output <ul class="menuUL">
    'liAttributesCallback' => 'customMenuLIAttr',      // ADVANCED: custom function to return li attributes, eg: 'myLiAttr' and function myLiAttr($category) { return "id='li_uniqueId_{$category['num']}'"; }
  ));

  function customMenuLIAttr($category) {
    global $GLOBALS;
    return ($category['_hasChild'])? " class=\"active sub-menu\"" : "" ;
  }

This is how the code looked when the classes were inserted into the <ul> and <li> tags. The remaining thing to achieve is the placement of the <span></span> tags.

<ul class="nav sf-menu clearfix"> // this is hardcoded in
 <li class="active sub-menu"><a href="#">Home</a><span></span> // class inserted by the CMSB getCategories function:: 'liAttributesCallback' => 'customMenuLIAttr',
  <ul class="submenu"> // class inserted by the CMSB getCategories function:: 'ulAttributes'=>'class="submenu"',
    <li><a href="#">Lorem ipsum dolor sit<span></span></a>
     <ul class="submenu"> // class inserted by the CMSB getCategories function:: 'ulAttributes'=>'class="submenu"',
      <li><a href="#">Lorem ipsum dolor sit</a></li>
      <li><a href="#">Conse ctetur adipisicing</a></li>
      <li><a href="#">Elit sed do eiusmod tempor</a></li>
      <li><a href="#">Incididunt ut labore</a></li>
      <li><a href="#">Et dolore magna aliqua</a></li>
     </ul>  
    </li>
    <li><a href="#">Conse ctetur adipisicing</a></li>
    <li><a href="#">Elit sed do eiusmod tempor</a></li>
    <li><a href="#">Incididunt ut labore</a></li>
    <li><a href="#">Et dolore magna aliqua</a></li>
   </ul>
  </li>
  <li><a href="#">About</a></li>
  <li><a href="#">Blog</a></li>
  <li><a href="#">Gallery</a></li>
  <li><a href="#">Contacts</a></li>
</ul>


The <span></span> tags is then controlled by CSS to insert a triangle pointing down or to the right to indicate that the menu was either a dropdown or expandable horizontally. For the dropdown menu it is to be inserted after the anchor tag is closed i.e. <a href="#">XX</a><span></span>. While for the horizontal expansion it must occur before the anchor tag closes i.e. <a href="#">YY<span></span></a>. To achieve this, I used conditional statements to determine the category depth and specify where to place the span tags.

<ul class="nav sf-menu clearfix">
<?php foreach ($navigation_menuRecords as $categoryRecord): ?>
  <?php echo $categoryRecord['_listItemStart'] ?>
  <?php if($categoryRecord['_hasChild'] && $categoryRecord['depth'] == '0'): ?>
    <b><a href="<?php echo $categoryRecord['url'] ?>"><?php echo $categoryRecord['name'] ?></a></b><span></span>
  <?php elseif($categoryRecord['_hasChild'] && $categoryRecord['depth'] > '0'): ?>
    <b><a href="<?php echo $categoryRecord['url'] ?>"><?php echo $categoryRecord['name'] ?><span></span></a></b>
<?php else: ?>
    <b><a href="<?php echo $categoryRecord['url'] ?>"><?php echo $categoryRecord['name'] ?></a></b>
  <?php endif ?>
  <?php echo $categoryRecord['_listItemEnd'] ?>
<?php endforeach; ?>
</ul>

This has taken me six days to figure out costing me a delay I could not afford.

Me thinks that had I gotten expert help from the authors of CMSB, this would have been solved a long time ago. Perhaps there is a new support policy that I have not read?

Terry

Terry, 

Glad you got it working!

This has taken me six days to figure out costing me a delay I could not afford.

Me thinks that had I gotten expert help from the authors of CMSB, this would have been solved a long time ago. Perhaps there is a new support policy that I have not read?

Sorry if you were wanting a response from us and we didn't reply.  Your last post said you were experimenting with the last posted approach.  Feel free to post a follow-up message in future, email us direct, or request custom programming if you need help faster.  We can't help with all custom programming requests, but with this one, I actually skipped over it because I thought you had it.

Dave Edis - Senior Developer
interactivetools.com

By terryally - September 23, 2017 - edited: September 23, 2017

Hi Dave,

Just above where I've placed this horizontal menu, I want to use the same getRecords array above it to output the "home" URL behind the page logo. I've done this using the first code below which does the trick. However a few lines later I am repeating the array to remove the LIMIT clause in order to populate the complete navigation menu using the second set of code. What I want to confirm is if there are any known problems with with CMSB if I called this the second time?

Thanks

<?php
  // load records from 'navigation_menu'
  list($navigation_menuRecords, $navigation_menuMetaData) = getRecords(array(
    'tableName'   => 'navigation_menu',
    'limit'       => '1',
    'loadUploads' => true,
    'allowSearch' => false,
  ));
?>

    <div class="box2">
        <div class="container"> 
        <?php foreach ($home_pageRecord['logo'] as $index => $upload): ?>
            <h1 class="navbar-brand navbar-brand_"><?php foreach ($navigation_menuRecords as $record): ?><a href="<?php echo htmlencode($record['url']) ?>"><?php endforeach ?><img src="<?php echo htmlencode($upload['urlPath']) ?>" alt="<?php echo htmlencode($upload['info1']) ?>"><span><?php echo htmlencode($upload['info1']) ?></span></a></h1>
        <?php endforeach ?>
        </div>
    </div>

  <?php
  // load records from 'navigation_menu'
  list($navigation_menuRecords, $selectedNavigation_menu) = getCategories(array(
    'tableName'            => 'navigation_menu', //
    'categoryFormat'       => 'showall',  // showall, onelevel, twolevel, breadcrumb
    'defaultCategory'      => 'first',    // Enter 'first', a category number, or leave blank '' for none
    'ulAttributes'         => 'class="submenu"',      // add html attributes to <ul> tags, eg: 'class="menuUL"' would output <ul class="menuUL">
    'liAttributesCallback' => 'customMenuLIAttr',      // ADVANCED: custom function to return li attributes, eg: 'myLiAttr' and function myLiAttr($category) { return "id='li_uniqueId_{$category['num']}'"; }
  ));
  function customMenuLIAttr($category) {
    global $GLOBALS;
    return ($category['_hasChild'])? " class=\"active sub-menu\"" : "" ;
  }
  ?>

    <div class="menuBox">  
        <div class="container"> 
            <nav class="navbar navbar-default navbar-static-top tm_navbar clearfix" role="navigation">
                <ul class="nav sf-menu clearfix">
                <?php foreach ($navigation_menuRecords as $categoryRecord): ?>
                  <?php echo $categoryRecord['_listItemStart'] ?>
                  <?php if($categoryRecord['_hasChild'] && $categoryRecord['depth'] == '0'): ?>
                    <b><a href="<?php echo $categoryRecord['url'] ?>"><?php echo $categoryRecord['name'] ?></a></b><span></span>
                  <?php elseif($categoryRecord['_hasChild'] && $categoryRecord['depth'] > '0'): ?>
                    <b><a href="<?php echo $categoryRecord['url'] ?>"><?php echo $categoryRecord['name'] ?><span></span></a></b>
                <?php else: ?>
                    <b><a href="<?php echo $categoryRecord['url'] ?>"><?php echo $categoryRecord['name'] ?></a></b>
                  <?php endif ?>
                  <?php echo $categoryRecord['_listItemEnd'] ?>
                <?php endforeach; ?>
              </ul>
        </div>
    </div

Hi Terry, 

There's no problem with calling it a second time, but it will overwrite the variables.  So for clarity you might use different variables such as replacing 

list($navigation_menuRecords, $navigation_menuMetaData) = getRecords(array(

with

list($navHeader_menuRecords, $navHeader_menuMetaData) = getRecords(array(

That said, if it's currently working there's no need to change it.

Hope that helps!

Dave Edis - Senior Developer
interactivetools.com

Thanks Dave. I like your solution better!