How to get CSS styled menu to maintain the open selected menu?

lgduong
lgduong used Ask the Experts™
on
Hello experts,

I have a CSS accordion menu that I would like to have the selected menu item continued to be open after a link is clicked.
For example, to get to the "chicken.php" page, the menu is expanded to the Food Management menu item.  If I want to click to the "beef.php" menu, it will maintain the expanded menu from the previous "chicken" page.

Here is my CSS menu:

            <div id="menu">
                  <ul class="cm-accordion-menu">
                                    <li class="main"><a href="/myhome.php">Home</a>
                        </li>
                        <li class="submenu">
                              <input type="checkbox" name ="group-aboutus" id="group-aboutus">
                              <label for="group-aboutus">About Us</label>
                              <ul>
                                    <li><a href="aboutFDP.php">About FDP</a></li>
                              </ul>
                        </li>

                        <!-- METRICS -->
                        <li class="submenu">
                              <input type="checkbox" name ="group-metrics" id="group-metrics">
                              <label for="group-metrics">Metrics</label>
                                    <ul>
                                          <li><a href="metric_home.php">Metrics Homepage</a></li>

                                          <!-- ACCESS MANAGEMENT -->
                                          <li class="submenu">
                                                <input type="checkbox" name ="subgroup-access" id="subgroup-access">
                                                <label for="subgroup-access">Access Management</label>

                                                <ul>
                                                      <li><a href="access.php">Access Status</a></li>
                                                      <li><a hre="access_report.php">Access Report</a></li>
                                                </ul>
                                          </li>  

                                          <!-- FOOD MANAGEMENT -->                                                
                                          <li class="submenu">
                                                <input type="checkbox" name ="subgroup-asset" id="subgroup-asset">
                                                <label for="subgroup-asset">Food Management</label>

                                                <ul>
                                                      <li><a href="dairy.php">Dairy</a></li>
                                                      <li><a href="beverages.php">Beverages</a></li>
                                                      <li><a href="produces.ph">Produces</a></li>
                                                      <li class="submenu">
                                                            <input type="checkbox" name ="subgroup-meatFood" id="subgroup-meatFood">
                                                                  <label for="subgroup-meatFood">Meat</label>
                                                                  <ul>
                                                                        <li><a href="chicken.php">Chicken</a></li>
                                                                        <li><a href="pork.php">Pork</a></li>
                                                                        <li><a href="beef.php">Beef</a></li>
                                                                        <li><a href="seafood.php">Seafood</a></li>
                                                            </ul>
                                                      </li>
                                                </ul>
                                          </li>
                              </ul>
                        </li>
                  </ul>
            </div>
styles.css
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Most Valuable Expert 2017
Distinguished Expert 2018

Commented:
How is your menu rendered when you click on a link? Is it a common include file?

What you need to do is when you render your menu you need to check the page you are going to and make sure you set the checkboxes in the menu hierarchy to checked for each node in the tree that leads to the destination page.

You can do it with JavaScript as well -
Requires jQuery to be loaded before this.
<script>
$(function() {
  var page = window.location.href.split('/').slice(-1);
  var link = $('a[href="' + page + '"]').closest('.submenu') || [];
  while (link.length > 0) {
    link.children('input').prop('checked',true);
    link = link.parent().closest('.submenu') || [];
  }
});
</script>

Open in new window


Edit
Changed false to [] as the check is on link.length - requires an object with a length property so using empty array.
Juana VillaFront-end Developer

Commented:
If I understand properly, you would like to click on a dropdown link and open that link on this current page and keep the dropdown open.

If this is the case, I would recommend you to think about it twice because it won't be a good user experience for your clients. Since, they already decided to read/interact with a specific page and now there is something in their way that is preventing them to do so.

However, you can add "target="_blank" to you <a> tags in order to keep that page open with the selected submenu open. Take in consideration that this might also be annoying since a new window will be open every time a dropdown link is clicked or use @Julian Hansen solution.

Author

Commented:
Julian,

I'm sorry that I forgot to mention that it is a left menu navigation.  It is a common include file.
What am I doing wrong?  
Due to the fact that I have other javascript files, I have to add a noconflict method to avoid conflicts.

Here is the code:

      <script type="text/javascript">
                  
                  var $jquery = jQuery.noConflict();
                  
                  $jquery(document).ready(function ()
                  {                        
                        var page = window.location.href.split('/').slice(-1);
                        
                        var link = $jquery('a[href="' + page + '"]').closest('.submenu') || [];
                        
                        alert("link is :: "+link);
                        
                        while (link.length > 0)
                        {
                              link.children('input').prop('checked',true);
                              link = link.parent().closest('.submenu') || [];
                        }
                  });

The alert message is "link is :: [objet Object]".  Why can't it get the closest submenu?  
I'm not proficient with jquery or javascript.

Please help.
Ensure you’re charging the right price for your IT

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden using our free interactive tool and use it to determine the right price for your IT services. Start calculating Now!

Most Valuable Expert 2017
Distinguished Expert 2018

Commented:
Instead of alert do this

console.log(link)

And then check the console (F7)

Is the menu the only place those links occur? It might be prudent to put a class on the menu and then prefix the selector with the class ex.

var link = $jquery('.main-menu a[href="' + page + '"]').closest('.submenu') || [];

Open in new window


Let's see what the console.log(link) does.

Author

Commented:
Julian,

The console displays "Object { length: 0, prevObject: Object }


When I manually add the "checked" to the first <input> it will expand that main menu but not any of the cascading submenu.
If I were to add "checked" to the 2nd or 3rd submenu, nothing is expanded, not even the "main" menu for that section.

for example, if checked is add to the 2nd submenu under Reports

<input type="checkbox" name ="subgroup-itReport" id="subgroup-itReport" checked>

the "main" menu section (Reports) is not expanded.


<div id="menu">
	<ul class="cm-accordion-menu">		
		<li class="submenu">
		
			[i][b]** if "checked" is true here, it will expand **[/b][/i]
			<input type="checkbox" name ="group-processes" id="group-processes" checked>
			<label for="group-processes">Processes</label>
				<ul>
					<li><a href="processHome.php">Processes Home</a></li>
					<li><a href="process1.php">Process1</a></li>
			</ul>
		</li>

		<li class="submenu">	
			[i][b]** if "checked" is true here, it will expand **[/b][/i]
			<input type="checkbox" name ="group-reports" id="group-reports" >
			<label for="group-reports">Reports</label>
			<ul>
				<li><a href="#0">ISCM Reports</a></li> 

				<li class="submenu">
					[i][b]** if "checked" is true here, nothing happen**[/b][/i]
					<input type="checkbox" name ="subgroup-itReport" id="subgroup-itReport" >
					<label for="subgroup-itReport">Reporting</label>

					<ul>											
						<li><a href="weekly.php">Weekly</a></li>
						<li class="submenu">
							[i][b]** if "checked" is true here, nothing happen**[/b][/i]
							<input type="checkbox" name ="subgroup-reportMonthly" id="subgroup-reportMonthly">
								<label for="subgroup-reportMonthly">Monthly</label>
								<ul>											
									<li><a href="report1.php">Report1</a></li>
									<li><a href="report2.php">Report2</a></li>										
							</ul>
						</li>									
					</ul>
				</li>
			</ul>
		</li>
	</ul>
</div>

Open in new window

Most Valuable Expert 2017
Distinguished Expert 2018

Commented:
This sample shows the case where you can manually add checked to the bottom

 <div id="menu">
	<ul class="cm-accordion-menu">		
		<li class="submenu">
		
			<input type="checkbox" name ="group-processes" id="group-processes">
			<label for="group-processes">Processes</label>
				<ul>
					<li><a href="processHome.php">Processes Home</a></li>
					<li><a href="process1.php">Process1</a></li>
			</ul>
		</li>

		<li class="submenu">	
			<input type="checkbox" name ="group-reports" id="group-reports" checked >
			<label for="group-reports">Reports</label>
			<ul>
				<li><a href="#0">ISCM Reports</a></li> 

				<li class="submenu">
					<input type="checkbox" name ="subgroup-itReport" id="subgroup-itReport" checked>
					<label for="subgroup-itReport">Reporting</label>

					<ul>											
						<li><a href="weekly.php">Weekly</a></li>
						<li class="submenu">
							<input type="checkbox" name ="subgroup-reportMonthly" id="subgroup-reportMonthly" checked>
								<label for="subgroup-reportMonthly">Monthly</label>
								<ul>											
									<li><a href="report1.php">Report1</a></li>
									<li><a href="report2.php">Report2</a></li>										
							</ul>
						</li>									
					</ul>
				</li>
			</ul>
		</li>
	</ul>
</div>

Open in new window

Working sample here

I applied the jQuery above to this menu as well and manually coded the page variable to test different scripts in the menu - all worked fine.

Author

Commented:
Julian,

You are absolutely right.  By adding the "checked" to all 3 level of the input field, it will keep those open.
Yet I am still having problems with the jquery method to the process to add the "checked" selector.

<script type="text/javascript">
var $jquery = jQuery.noConflict();

$jquery(function() 
{
	var page = window.location.href.split('/').slice(-1);

	var link = $jquery('a[href="' + page + '"]').closest('.submenu') || false;
	
	alert("link is :: "+link);
	
	while (link.length > 0) 
	{
		link.children('input').prop('checked',true);
		link = link.parent().closest('.submenu') || false;
	}
});
</script>

Open in new window


The alert message is "link is :: [object Object]".  
What is wrong with my jquery that it is not giving me the "link"?

Please be patience with me.  jQuery/javascript is really not my strong point.
Most Valuable Expert 2017
Distinguished Expert 2018

Commented:
The alert message is "link is :: [object Object]".  
There is nothing wrong with this message - it is what you should see in an alert. Which is why I suggested you use console.log(link) instead - the console shows a lot more information.

Add this at line 7
console.log(page)

We need to check that the page that is being retrieved matches a link on the page. Also change window.location.href to window.location.pathname

<script>
$(function() {
  var page = window.location.pathname.split('/').slice(-1);
  console.log(page);  
  var page = 'access_report.php';
  var link = $('a[href="' + page + '"]').closest('.submenu') || false;
  console.log(link);
  while (link.length > 0) {
    link.children('input').prop('checked',true);
    link = link.parent().closest('.submenu') || false;
  }
});
</script>

Open in new window

Author

Commented:
Hi Julian,

I've converted my webpage to html extension and it does work.  However, if the url link is an absolute path or a layer deeper, it does not work in expanding the menu.  What am I doing work or missing?

 <div id="menu">
	<ul class="cm-accordion-menu">		
		<li class="submenu">
		
			<input type="checkbox" name ="group-processes" id="group-processes">
			<label for="group-processes">Processes</label>
				<ul>
					<li><a href="/home/processHome.php">Processes Home</a></li>
					<li><a href="/home/proc/process1.php">Process1</a></li>
			</ul>
		</li>

		<li class="submenu">	
			<input type="checkbox" name ="group-reports" id="group-reports" checked >
			<label for="group-reports">Reports</label>
			<ul>
				<li><a href="#0">Reports</a></li> 

				<li class="submenu">
					<input type="checkbox" name ="subgroup-itReport" id="subgroup-itReport" checked>
					<label for="subgroup-itReport">Reporting</label>

					<ul>											
						<li><a href="weekly.php">Weekly</a></li>
						<li class="submenu">
							<input type="checkbox" name ="subgroup-reportMonthly" id="subgroup-reportMonthly" checked>
								<label for="subgroup-reportMonthly">Monthly</label>
								<ul>											
									<li><a href="level1/report1.php">Report1</a></li>
									<li><a href="level1/report/report2.php">Report2</a></li>										
							</ul>
						</li>									
					</ul>
				</li>
			</ul>
		</li>
	</ul>
</div>

Open in new window

Author

Commented:
Julian or anyone,

Can you please help me with the new problem of the link being several layers (/level1/level2/page.html) instead of only one layer (page.html)?


Thanks.
Most Valuable Expert 2017
Distinguished Expert 2018
Commented:
Just change your selector on the href to wildcard ends with
<script>
$(function() {
  var page = window.location.pathname.split('/').slice(-1);
  // CHANGE THIS TO href$
  var link = $('a[href$="' + page + '"]').closest('.submenu') || false;
  console.log(link);
  while (link.length > 0) {
    link.children('input').prop('checked',true);
    link = link.parent().closest('.submenu') || false;
  }
});
</script>

Open in new window

Author

Commented:
Thank you for your help.
Most Valuable Expert 2017
Distinguished Expert 2018

Commented:
You are welcome.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial