Help pulling information from a 5-tiered menu category

12 posts by 2 authors in: Forums > CMS Builder
Last Post: February 18, 2010   (RSS)

By dbown - February 15, 2010

Hello, I have a 5-tiered category that I have working with a dynamic menu.

I would now like to pull 3 pieces of information from the menu for display on the final page that is currently being viewed.

Here is a link that takes you to a view of a page on the 5th tier.
Link: http://www.tutormyself.com/new/page.php?Mathematics-Whole-Numbers-Whole-number-numeracy-Numbers-to-10-Count-objects-to-10-36

Issue 1) On the top of the left menu I would like the title of the parent category to be dynamically displayed. Currently it is hard coded. If you run over the navigation menu you'll see that we are on the page called "Count objects to 10". This pages parent is "Numbers to 10".

Issue 2) I would like to list all the siblings on the selected category. These are hard currently coded on the page you are seeing. Please not we will not always be on the 5 tier. Some math categories do not need to go as deep before providing the content pages.

The attached screenshot helps to identify the first two issues.


Issue 3) I need to list a breadcrumb trail across the top that has links to the detail matching the selected item.
I have found this code "<?php echo $categoryRecord['breadcrumb'] ?>" that produces the text that matches my requirement however there are no links and I would like to have a separator between each value.


Here is my top of page code

<?php

require_once "/home/bbd/public_html/cmsAdmin/lib/viewer_functions.php";

list($categoryRecordsMenu) = getCategories(array(
'tableName' => 'category',
'categoryFormat' => 'showall', // showall, onelevel, twolevel
));

list($categoryRecords, $categoryMetaData) = getRecords(array(
'tableName' => 'category',
'where' => whereRecordNumberInUrl(1),
'limit' => '1',
));
$categoryRecord = @$categoryRecords[0]; // get first record

// show error message if no matching record is found
if (!$categoryRecord) {
header("HTTP/1.0 404 Not Found");
print "Record not found!";
exit;
}
?>



Here is my Navigation Menu Code:
<div style="margin:0px auto;" id="smoothmenu1" class="ddsmoothmenu">
<ul>
<?php foreach ($categoryRecordsMenu as $categoryRecordMenu): ?>
<?php echo $categoryRecordMenu['_listItemStart'] ?><a href="<?php echo $categoryRecordMenu['_link'] ?>"><?php echo $categoryRecordMenu['name'] ?></a><?php echo $categoryRecordMenu['_listItemEnd'] ?>
<?php endforeach; ?>
</ul>
<br style="clear: left" />
</div>


I have some other code that is being used to display the content for all the tab fields on the page. If you need to see that just let me know.

Thanks,
Dave

Re: [dbown] Help pulling information from a 5-tiered menu category

By Chris - February 15, 2010 - edited: February 16, 2010

Hi Dave,

I've written up some code for you to extract the data you want for all three issues. Firstly, let's change your STEP 1 code to a single getCategories call (getRecords isn't necessary):

<?php

require_once "/home/bbd/public_html/cmsAdmin/lib/viewer_functions.php";

list($categoriesRecords, $selectedCategory) = getCategories(array(
'tableName' => 'category',
'categoryFormat' => 'showall', // showall, onelevel, twolevel
));

// show error message if no matching record is found
if (!$selectedCategory) {
header("HTTP/1.0 404 Not Found");
print "Record not found!";
exit;
}
?>


Now add this code to the bottom of STEP 1:

<?php
$categoriesRecordsByNum = array_combine(array_pluck($categoriesRecords, "num"), $categoriesRecords);

$lineage = explode("\t", trim(preg_replace("/:/", "\t", $selectedCategory['lineage'])));

$immediateParent = sizeof($lineage) < 2 ? 0 : $lineage[sizeof($lineage)-2];
$immediateParent = $immediateParent ? $categoriesRecordsByNum[$immediateParent] : null;

$parents = array();
foreach ($lineage as $parentCatNum) {
$parents[] = $categoriesRecordsByNum[$parentCatNum];
}

$siblingLineage = preg_replace("/:\d+:$/", ":", $selectedCategory['lineage']);
$siblings = array();
foreach ($categoriesRecords as $category) {
if (preg_match("/^$siblingLineage\d+:$/", $category['lineage'])) {
$siblings[] = $category;
}
}
?>


Now that you've made available the $immediateParent, $parents, and $siblings variables, you can use them like this:

Immediate Parent Category: <?php if ($immediateParent): ?><a href="<?php echo $immediateParent['_link'] ?>"><?php echo $immediateParent['name'] ?></a><?php else: ?>None<?php endif ?><br />

Breadcrumbs with links <?php foreach($parents as $parent): ?>
: <a href="<?php echo $parent['_link'] ?>"><?php echo $parent['name'] ?></a>
<?php endforeach ?><br />

Sibling Categories:<ul>
<?php foreach($siblings as $sibling): ?>
<?php if ($sibling['num'] == $selectedCategory['num']) { continue; } ?>
<li><a href="<?php echo $sibling['_link'] ?>"><?php echo $sibling['name'] ?></a></li>
<?php endforeach ?></ul>


Note that $siblings actually includes the selected category, but we skip over it (via "continue") when displaying.

I hope this helps! Please let me know if you have any questions.
All the best,
Chris

Re: [dbown] Help pulling information from a 5-tiered menu category

By dbown - February 15, 2010

Wow, that was incredibly fast a amazingly helpful. I honestly thought that those problems would take a week to get working. Thank you so much.

Hopefully you can answer a few more questions for too.

Please see Link:
http://www.tutormyself.com/new/page.php?Mathematics-Whole-Numbers-Whole-number-numeracy-Numbers-to-10-32

This is direct link to a content page that is neither at the top or bottom of the structure.

(1) I was hoping you could help me make links within this page to the children of the current page. I have hard coded this menu into the top of the centre column to show you what I was hoping for. Essentially this allow my visitors to navigate down the category structure without having to rely on the over-sensitive menu.

(2) Also, regarding the sibling list in the left menu, it would great to actually list the the current unit (bolded) in the correct order that it would normally appear.

So on this page the unit "Numbers to 10" would be bolded on the top of the little link list.

(3) The breadcrumbs work perfect. I added a link to the Home page in front of the code you provided as it started with >> .
I would like the bread crumb list to appear for all pages in the categories listing except for the home page. This is because the home page reads as "Home >> Home". you can click on the home link to see.

Is there an easy way to exclude the breadcrumbs code if the home page is being viewed?


I kept the records code in place as I was using it to load the content on the page for each particular page. I have attached my code this time.
Attachments:

page.php 14K

Re: [dbown] Help pulling information from a 5-tiered menu category

By Chris - February 16, 2010 - edited: February 16, 2010

Hi Dave,

Glad I could help! :)

1. You want a list of the immediate children of the current category? Here's how:

<?php
$immediateChildren = array();
foreach ($categoriesRecords as $category) {
if (preg_match("/^" . $selectedCategory['lineage'] . "\d+:$/", $category['lineage'])) {
$immediateChildren[] = $category;
}
}
?>
Immediate Children:<ul>
<?php foreach($immediateChildren as $immediateChild): ?>
<li><a href="<?php echo $immediateChild['_link'] ?>"><?php echo $immediateChild['name'] ?></a></li>
<?php endforeach ?></ul>


2. I've changed the $sibling code in my post above to include the selected category (and changed the example code to skip over it). This way, the code is more flexible. Now you can do this:

Parent's Children:<ul>
<?php foreach($siblings as $sibling): ?>
<?php $isSelected = ($sibling['num'] == $selectedCategory['num']) ?>
<li>
<?php if ($isSelected): ?><b><?php endif ?>
<a href="<?php echo $sibling['_link'] ?>"><?php echo $sibling['name'] ?></a>
<?php if ($isSelected): ?></b><?php endif ?>
</li>
<?php endforeach ?></ul>


3. Yes, you can wrap your breadcrumb code in an IF block to cause it not to display if $selectedCategory['num'] is 1:

<a href="?Home-1">Home</a>
<?php if ($selectedCategory['num'] != 1): ?>
<?php foreach($parents as $parent): ?>
: <a href="<?php echo $parent['_link'] ?>"><?php echo $parent['name'] ?></a>
<?php endforeach ?><br />
<?php endif ?>


I hope this helps! Please let me know if you have any questions.
All the best,
Chris

Re: [dbown] Help pulling information from a 5-tiered menu category

By dbown - February 16, 2010

Hi Chris,

Thanks once again! It's great to see such detailed and quick support for these functions.

Your replies regarding items 1 and 3 worked perfectly. These items related to the Immediate Children list and the Hiding of the Home page breadcrumb menu.

There might be a glitch in the code for displaying the current category alongside it siblings though.

Just in case I didn't describe my issue too well I'll try by example.
Link: http://www.tutormyself.com/new/page.php?Mathematics-Whole-Numbers-Whole-number-numeracy-Numbers-to-10-32

If you follow the link you will be taken to a page called "Numbers to 10". This page has a series of other sub pages (i.e children) but it also has 3 other siblings. (i.e. Numbers to 30, Numbers to100, & Numbers to 1000).

What I was hoping to see is for the name of this current unit to be visible at the top of the left column menu titled Parent's Children. I was also hoping that the current unit could be bolded as well as this will help my vistors know which unit they are currently viewing.

However, the current unit is should not always be located at the top of the list. If we were visit the "Numbers to 30" unit then I would like this unit to be the displayed in the left column list in the second position below "Numbers to 10".

Is this functionality possible?

Best Regards,
Dave
Attachments:

page_001.php 14K

Re: [dbown] Help pulling information from a 5-tiered menu category

By Chris - February 18, 2010

Hi Dave,

I made a change to the code the code that generates the $sibling array above. Sorry, I should have showed you what that change was. You'll need to remove the code in red from your page:

$siblingLineage = preg_replace("/:\d+:$/", ":", $selectedCategory['lineage']);
$siblings = array();
foreach ($categoriesRecords as $category) {
if (preg_match("/^$siblingLineage\d+:$/", $category['lineage']) && $category['num'] != $selectedCategory['num']) {
$siblings[] = $category;
}
}


I think you'll get the results you want by making this change.

Please let me know if you have any questions! :)
All the best,
Chris

Re: [chris] Help pulling information from a 5-tiered menu category

By dbown - February 18, 2010

Hi Chris,

Thanks that worked perfect.

I have another issue regarding the menu I was hoping you could help with too.

At the end of each menu branch I will be adding a series of exercise pages. Essentially, this makes a 6th tier for the few topic where the tree branches down that far. In most cases however, these exercise pages will be located in the 3rd, 4th or 5th tier.

I have added 3 "Exercise" pages to the final section
Link: http://www.tutormyself.com/new/page.php?Mathematics-Whole-Numbers-Whole-number-numeracy-Numbers-to-10-Count-objects-to-10-36

I have also added 3 "Exercise" pages to the Measurement --> Measure length" section to show you these exercise pages can be higher in the menu structure.


I would like for the last series of Exercise pages to be removed from the main drop down navigation menu. If is fine for these pages to be listed in the breadcrumbs and in the children pages list.

Our rational is that we want all our students to first visit the page that introduces a math concept before starting the exercises.


I have added a checkbox field to the records for each page call Lastmenu. The idea was that if this checkbox is clicked then the Navigation Menu code can detect that and not list the final menu that would only contain exercise pages.

I tried this code on the page...
<?php if ($categoryRecord['lastmenu'] != 1): ?> CODE TO GENERATE DROP DOWN MENU<?php endif ?>

But realized that the categories menu code isn't reading the individual records as it is being called via getCategories rather then getRecords.

I don't now the nuances as to how the codes get called here or even if my technique is possible.

Can you please help me get my technique working or advise me on how to code a better approach?

Thanks for all your help so far.

Cheers,
Dave
Attachments:

remove_menu.jpg 205K

page_002.php 14K

Re: [dbown] Help pulling information from a 5-tiered menu category

By Chris - February 18, 2010 - edited: February 18, 2010

Hi Dave,

That's very tricky.

I would solve this by using a checkbox field for whether or not the record is an exercise (and should therefore not be displayed in the top navigation menu.) Then, I'd build up a menu into a string, skipping over entries which have "exercise" checked, but including their UL and LI tags. Finally, I'd iteratively run a couple regexps on the string to remove any empty UL and LI tags:

<?php
$menu = "";
foreach ($categoryRecordsMenu as $categoryRecordMenu) {
$menu .= $categoryRecordMenu['_listItemStart'];
if (!$categoryRecordMenu['exercise']) {
$menu .= '<a href="' . $categoryRecordMenu['_link'] . '">' . htmlspecialchars($categoryRecordMenu['name']) . '</a>';
}
$menu .= $categoryRecordMenu['_listItemEnd'];
}

while (true) {
$oldMenu = $menu;

$menu = preg_replace('|\s*<li[^>]*>\s*</li[^>]*>\s*|i', '', $menu);
$menu = preg_replace('|\s*<ul[^>]*>\s*</ul[^>]*>\s*|i', '', $menu);

// if we haven't changed anything, we're done
if ($menu == $oldMenu) { break; }
}

echo($menu);
?>


I hope this helps! Please let me know if you have any questions.
All the best,
Chris

Re: [dbown] Help pulling information from a 5-tiered menu category

By Chris - February 18, 2010

Hi Dave,

The code I posted is meant to work with a checkbox field named "excercise".
All the best,
Chris