Category Menu

5 posts by 2 authors in: Forums > CMS Builder
Last Post: September 9, 2019   (RSS)

By rez - September 5, 2019 - edited: September 6, 2019

I made a Category Menu and some root levels have children and some don't.

The html has to come out like below.

<ul class="dropdown menu" data-dropdown-menu>
  <li>
    <a href="#">Item 1</a>
    <ul class="menu">
      <li><a href="#">Item 1A</a></li>
      <!-- ... -->
    </ul>
  </li>
  <li><a href="#">Item 2</a></li>
  <li><a href="#">Item 3</a></li>
  <li><a href="#">Item 4</a></li>
</ul>

Notice the UL goes after the <a>, and not inside of it. So any root level that has children have the anchor and the whole UL inside of the li.  I don't seem to have control of where internal ul tags go so I'm lost My attempts are basically moving around the default CMSB category code. I figured the li had to go in each if statement? What I'm putting here is basically one of 10 attempts but is clearly wrong. I'm lost.

  // load records from 'menu_items'
  list($menu_itemsRecords, $menu_itemsMetaData) = getRecords(array(
    'tableName'   => 'menu_items',
    'loadUploads' => true,
    'allowSearch' => false,
  ));
  // load records from 'menu_cats'
  list($menu_catsRecords, $selectedMenu_cats) = getCategories(array(
    'tableName'            => 'menu_cats', //
    'categoryFormat'       => 'showall',  // showall, onelevel, twolevel, breadcrumb
    'defaultCategory'      => '',    // Enter 'first', a category number, or leave blank '' for none
    
    // advanced options (you can safely ignore these)
    'rootCategoryNum'      => '0',      // Only categories _below_ this one will be shown (defaults to blank or 0 for all)
    'ulAttributes'         => 'class="menu"',      // 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)
  ));




						<ul class="dropdown menu" data-dropdown-menu>
							<?php foreach ($menu_catsRecords as $categoryRecord): ?>

									<?php if($categoryRecord['_hasChild'] && $categoryRecord['depth'] == '0'): ?>
										<?php echo $categoryRecord['_listItemStart'] ?>							
											<a href="#"><?php echo $categoryRecord['name'] ?></a>
									<?php else: ?>
										<?php echo $categoryRecord['_listItemStart'] ?>
											<a href="<?php echo $categoryRecord['name'] ?>"</a>
									<?php echo $categoryRecord['_listItemEnd'] ?>
									<?php endif ?>

							<?php endforeach; ?>
						</ul>






By rez - September 6, 2019 - edited: September 6, 2019

I removed else statements and I don't know how this works but it does. It seems to me I would have to detect a lastchild in depth 2 to add the closing _listItemEnd tag for that branch's depth zero. I have a _listItemStart without a listItemEnd.

I moved some categories around and it doesn't break. Obviously this won't work on a menu with more than a depth of 2. Maybe you can help me with that to future proof this with unlimited depths / sub categories?

Am I getting lucky here and somehow a mistake happens to work? I don't get why this works. I troubleshooted and just came up with it logically.  

						<ul class="dropdown menu" data-dropdown-menu>
							<?php foreach ($menu_catsRecords as $categoryRecord): ?>
									<?php // If the category is depth zero and has children, put an opening li and a linked name. No closing li yet.?>
									<?php if($categoryRecord['_hasChild'] && $categoryRecord['depth'] == '0'): ?>
										<?php echo $categoryRecord['_listItemStart'] ?>
											<a href="#"><?php echo $categoryRecord['name'] ?></a>
									<?php endif; ?>
							    <?php // if the category does not have children and is greater than depth zero, not last, must be depth 2, put a linked name with opening and closing li ?>
										<?php if(!$categoryRecord['_hasChild'] && $categoryRecord['depth'] > '0' && !$categoryRecord['_isLastChild']): ?>
											<?php echo $categoryRecord['_listItemStart'] ?>
												<a href="#"><?php echo $categoryRecord['name'] ?></a>
											<?php echo $categoryRecord['_listItemEnd'] ?>
										<?php endif; ?>
							    <?php //if the category is the last child in this current loop, greater than depth zero, that means we need an extra closing li for this branch's depth zero EDIT: removed it ?>
											<?php if($categoryRecord['_isLastChild'] && $categoryRecord['depth'] > '0'): ?>
												<?php echo $categoryRecord['_listItemStart'] ?>
													<a href="#"><?php echo $categoryRecord['name'] ?></a>
												<?php echo $categoryRecord['_listItemEnd'] ?>							
											<?php endif; ?>
								  <?php // otherwise, opening and closing li around a linked name should cover everything else ?>
										<?php if(!$categoryRecord['_hasChild'] && $categoryRecord['depth'] == '0'): ?>
											<?php echo $categoryRecord['_listItemStart'] ?>
												<a href="#"><?php echo $categoryRecord['name'] ?></a>
											<?php echo $categoryRecord['_listItemEnd'] ?>
									<?php endif; ?>
							<?php endforeach; ?>
						</ul>

By daniel - September 6, 2019

Hey rez,

The behaviour you're describing (nesting <ul> outside of the <a></a>) is - I believe - supposed to be the default category menu behaviour. It looks like that might be what you're recreated in your latest "working" attempt. I would suggest trying the code generator again and checking to see if/how the default output is different from your custom example. If the default output isn't getting what you want, then there might be a different issue at play.

In any case, if you want to customize the nesting in a category menu, I'd recommend inserting the tags (li, ul, etc.) themselves, rather than using the _listItemStart and _listItemEnd values, since these are generated in accordance with the default behaviour and won't be much help otherwise. This is, however, a much more complex method, and a bit beyond what I'd be able to demonstrate on the forum.

Let me know how it goes trying the default output, or if you have any other questions.

Thanks!

Daniel
Technical Lead
interactivetools.com

By rez - September 9, 2019 - edited: November 16, 2019

I see what I was doing wrong with the default code now that you have told me this.