Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

We've moved the forum!

Please use forum.silverstripe.org for any new questions (announcement).
The forum archive will stick around, but will be read only.

You can also use our Slack channel or StackOverflow to ask for help.
Check out our community overview for more options to contribute.

Template Questions /

Moderators: martimiz, Sean, Ed, biapar, Willr, Ingo, swaiba

Dividing menu items into groups


Go to End


10 Posts   6385 Views

Avatar
sca123

Community Member, 61 Posts

17 July 2009 at 8:33pm

I need help splitting menu items up into four groups, so for example:

If X is the number of menu items (we'll place a value of X as 20)
So X / 4 (20/4) is 5
and then every 5 menu items, close and open div (to split the menu on the front end)

The problem comes when X is say 21, which would need to result in 6 menu items in the first column and 5 menu items in the remaining 3 columns.

Hopes this makes sense. Thanks in advance for any help.

Avatar
bummzack

Community Member, 904 Posts

17 July 2009 at 9:02pm

The "modulo" operator (%) will give you the remaining value when doing integer division. Example: 21 % 4 results in 1, since 1 will remain when 21 is divided by 4 (integer division). In your case, using modulo, you'll only get 4 different cases:
Modulo returns 0: X can be divided by 4, no problems.
Modulo returns 1: one item has to be added to the first row
Modulo returns 2: one item has to be added to row 1 and 2
Modulo returns 3: one item has to be added to rows 1 - 3

Avatar
bummzack

Community Member, 904 Posts

17 July 2009 at 9:33pm

Edited: 17/07/2009 9:34pm

Just wanted to test this and wrote a function that does what you want:

// place this in your Page_Controller
public function GridMenu($level, $numLines){
	$items = $this->Menu($level);
	$numItems = $items->Count();
	$remaining = $numItems % $numLines;
	$itemsPerLine = floor($numItems / $numLines);
	$rows = array();
	$it = $items->getIterator();
	
	for($i = 0; $i < $numLines; ++$i){
		$row = new DataObjectSet();
		$t = $itemsPerLine + ($i < $remaining ? 1 : 0); 
		for($k = 0; $k < $t; ++$k){
			$row->push($it->current(), $it->key());
			$it->next();
		}
		$rows[] = array('Row' => $row);
	}
	return new DataObjectSet($rows);
}

The method works in the same way as Menu(x), but takes two parameters GridMenu($level, $numLines) where $level is the menu level and $numLines is the amount of lines or rows to output.

In the template you would use this like shown below:

<% control GridMenu(1, 4) %>
	<div>
	<% control Row %>
		<span>$Title</span>
	<% end_control %>
	</div>
<% end_control %>

This would output your pages of level 1 and split them into 4 rows. As you can see there's an inner loop (<% control Row %>) that outputs the items of a row.

Avatar
sca123

Community Member, 61 Posts

17 July 2009 at 9:42pm

Thank you - this most definately looks like the control required. How would this be modified to include the control <% if ChildrenOf() %> as my first level menu is made up of fixed images so I would need to have this control to show the second level menu (in groups of 4) just for that parent.

Thanks in advance

Avatar
sca123

Community Member, 61 Posts

17 July 2009 at 9:46pm

Also would $numlines not need to be dynamic in the template?

Avatar
sca123

Community Member, 61 Posts

17 July 2009 at 9:49pm

Just to help you help me a little more - here is the code that needs to be dynamically created for a level2 menu grouping:

    <div id="appdiv3" onmouseover="MM_showHideLayers('appdiv3','','show')" onmouseout="MM_showHideLayers('appdiv3','','hide')">
    	<div class="god_div">
        	<div class="red_drop_top"><img src="/themes/blackcandy/images/festival_top_round.png"  alt="empty"/></div>
            <div class="red_drop_down">
            	<div class="red_info_link">
                	<ul>
                    	<li><a href="#" id="act">About us</a></li>
                        <li><a href="#">Camping Village</a></li>
                        <li><a href="#">Car Parking</a></li>
                        <li><a href="#">Charities</a></li>
                        <li><a href="#">Directions</a></li>
                    </ul>
                </div>
                
                <div class="red_info_link">
                	<ul>
                    	<li><a href="#">Facebook</a></li>
                        <li><a href="#">FAQ</a></li>
                        <li><a href="#">Feedback Form</a></li>
                        <li><a href="#">Hotels</a></li>
                        <li><a href="#">Merchandise</a></li>
                    </ul>
                </div>
                
                <div class="red_info_link">
                	<ul>
                    	<li><a href="#">News</a></li>
                        <li><a href="#">Shuttle Bus</a></li>
                        <li><a href="#">Venue Map</a></li>
                        <li><a href="#">What is 7s</a></li>
                        <li><a href="#">World Tournaments</a></li>
                    </ul>
                </div>
                
                <div class="red_info_link">
                	<ul>
                    	<li><a href="#">2012 Olympics</a></li>
                        <li><a href="#">Contact Us</a></li>
                    </ul>
                </div>
            </div>
            <div class="red_drop_top"><img src="/themes/blackcandy/images/festival_bottom_round.png"  alt="empty"/></div>
        </div>
  </div>

Avatar
bummzack

Community Member, 904 Posts

17 July 2009 at 10:09pm

Well. You could simply rewrite the code to use ChildrenOf instead of Menu.

// remove this line:
// $items = $this->Menu($level); 
// add this line:
$items = $this->ChildrenOf($level); 

Then instead of calling GridMenu(1,4) you would use GridMenu(page-url, 4)

Why does $numLines have to be dynamic? In your first post you wrote that you need 4 lines of items. I wrote it more generically to allow arbitrary number of lines using the second parameter.

Avatar
sca123

Community Member, 61 Posts

17 July 2009 at 10:30pm

They need to be in columns rather than rows.

Go to Top