How to make selected link in Navigation highlighted when clicked [duplicate] - php

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I highlight a link based on the current page?
Context
I have been trying for ages to get a selected link in my Navigation menu to stay highlighted when clicked, but I cant find any decent understandable tutorials on this.
Questions
How can I resolve this?
Would jQuery or PHP be best for this?
Code
<ul>
<li>ABOUT US
<ul>
<li>Company</li>
<li>Team</li>
<li>Careers</li>
</ul>
</li>
<li>OUR WORK
<ul>
<li>Portfolio</li>
<li>Upcoming</li>
</ul>
</li>
<li>WHATS NEW
<ul>
<li>News</li>
<li>Blog</li>
</ul>
</li>
</ul>

Solution
The cleaner is to add a current class to selected link when you generate the page on the server side.
Example
I found this example which is close to your current architecture, according to the code that you gave us.
Source: http://www.finalwebsites.com/tutorials/css-navigation-bar.php
PHP
$items = array(
array('link'=>'scripts.html', 'label'=>'PHP scripts'),
array('link'=>'tutorials.html', 'label'=>'Tutorial'),
array('link'=>'template.html', 'label'=>'CSS template'),
array('link'=>'examples.html', 'label'=>'Code examples')
);
$menu = '<ul>';
foreach ($items as $val) {
$class = ($_SERVER['SCRIPT_NAME'] == $val['link']) ? ' class="current"' : '';
$menu .= sprintf('<li>%s</li>', $val['link'], $val['label']);
}
$menu .= '</ul>';
echo $menu;
CSS
ul li a.current { background-color: #40611F; color: #FFFFFF; }

Related

Update Header link class on page change php

I am trying to make a dynamic header in which header link classes update automatically when the page changes. so, like if the user in on index then HOME on header shows in red and if he is on folio page then folio shows in red and so on.
my code.
<?php
switch(basename($_SERVER['PHP_SELF'])){
case "index.php":
$index_hover = "act-link";
break;
case "portfolio.php":
$folio_hover = "act-link";
break;
}
?>
<style>
.act-link {color: red}
</style>
<div class="nav-holder">
Home
Folio
</div>
This code works as expected but the issues say I have 30 links in the header then it's not handy. so I want to make it dynamic so that it detects the page and update as per the need.
Thanks
From your question i think you want to add custom class in navigation menu associated with page
You can do it using php and javascript as well
Using PHP
<?php
function addActiveClass($page){
$url_array = explode('/', $_SERVER['REQUEST_URI']) ;
$url = end($url_array);
if($page == $url){
echo 'act-link'; //class name in css
}
}
?>
<ul>
<li><a class="<?php addActiveClass('home.php');?>" href="http://localhost/Home.php">Home</a></li>
<li><a class="<?php addActiveClass('aboutus.php');?>" href="http://localhost/aboutus.php">About us</a></li>
<li><a class="<?php addActiveClass('contactus.php');?>" href="http://localhost/contactus.php">Contact us</a></li>
</ul>
Here i have added function on every anchor tag addActiveClass which adds class 'act-link' depending on argument passed
Using javascript(jquery)
$(document).ready(function() {
var pathname = window.location.pathname;
$('ul > li > a[href="'+pathname+'"]').parent().addClass('act-link');
})
<ul class="nav">
<li>Home</li>
<li>About us</li>
<li>Contact us</li>
</ul>
I have used jquery here if you want you can write code is core js as well
let me know if there is confusion

JQuery show and hide data from a query in list format that displays parent clickable list that opens its child list

I am going to try and explain this as clearly as I can.
I am working with some script from #Prabu Parthipan which uses JQuery to open and close child lists of parent lists.
I have a query that returns an array of data. In the array I have two fields:
SeqHeader
SeqText
Each SeqHeader has variable number of SeqText items.
Example:
SeqHeader:Bedroom Door & Frame (inside & Outside)
SeqText:Chipped - Scratched - Stained - Needs Paint
SeqText:Chipped - Threshold - Sand/Stain - Repair
SeqText:Door Hinges - Squeaks/Sticks - Requires Oil/Repair
SeqHeader:Entry Door Lock
SeqText:Room Door Handle/Strike plate - Not Secure/Not Working
SeqText:Security Door Chain - Not Working
SeqText:Room Door Dead Lock - Not operating Correctly
SeqHeader:Bathroom Door Lock
SeqText:Door Handle/Strike plate - Not secure/Not Working
SeqText:Door Lock - Inoperable
I could display the above as rows using a PHP do while loop but I though it would be better to produce a list with sublists that open and close.
So adopting Prabu Parthipan code
#Prabu Parthipan code is:
$(document).ready(function(){
$('ul li.expanded > a')
.attr('data-active','0')
.click(function(event){
$('.submuneu').hide();
if($(this).attr('data-active')==0){
$(this).parent().find('ul').slideToggle('slow');
$(this).attr('data-active','1');
}
else
$(this).attr('data-active','0');
});
$('a.on').click(function(){
$('a.on').removeClass("active");
$(this).addClass("active");
});
});
In the body of the page I have:
<?php do { ?>
<tr>
<td colspan="3" class="imaindateselleft_padding">
<div class="leftsidebar_templ1">
<ul id="nav">
<li class="expanded"><a class="on"><?php print $row_AuditItems['SeqHeader']; ?></a>
<ul class="submuneu">
<li><a><?php print $row_AuditItems['SeqText']; ?></a> </li>
</ul>
</li>
</ul>
</div>
</td>
<td class="imaindatesel"> </td>
</tr>
<?php } while ($row_AuditItems = mysql_fetch_assoc($AuditItems)); ?>
As it is when the page is loaded it displays a SeqHeader for each SeqText. They are clickable and when clicked they open up the sub list.
What I want to do is have all the SeqText items relating to thier parent SeqHeader as a sublist so when the SeqHeader is clicked all the related sub items show, and click again so they hide.
Sorry if I have rabbled on.
Any help would be great and I thank you for your time.
Cheers.
Wouldn't it make more since to make a simple to use multi-dimensional array of the items you're getting? As I gather, you're using the deprecated mysql call to get rows of info from a DB. Each row will have the Header and the Text associated. Thus, if you call inline by each, row, you'll have a header for each row. Try the following instead.
<?php
$res = array();
while ($row = mysql_fetch_assoc($AuditItems)) {
if ($row['SeqHeader'] && $row['SeqText']) {
if (!$res[$row['SeqHeader']]) $res[$row['SeqHeader']] = array();
$res[$row['SeqHeader']][] = $row['SeqText'];
}
}
?>
<ul id="nav">
<?php foreach ($res as $k => $v): ?>
<li class="expanded">
<a class="on"><?php echo $k; ?></a>
<ul class="submuneu">
<?php foreach ($v as $item): ?>
<li><a><?php echo $item; ?></a></li>
<?php endforeach; ?>
</ul>
</li>
<?php endforeach; ?>
</ul>
I believe you're biggest problem now is in HTML layout. But this should help that. Fix that and then determine if the JS is still a problem, though what you want in JS is relatively easy.
Example of Easy JavaScript for dealing with opening and closing submenus using HTML Markup as:
UL > LI > A + UL > LI > A
// simply jQuery shorthand for document.ready = function() { ...
$(function() {
// the following is how to add events so that they work for even "dynamically" created elements.
// That is, elements created after code/page load.
$(document).on('click', 'li a', function(e) {
e.preventDefault(); // ensure it doesn't try to follow a link
// close all possible siblings and cousins
$(this).parents('li').each(function(i) { $(this).siblings().find('ul').slideUp(); });
// slide toggle current possible sub menu
$(this).next('ul').slideToggle(function() { if (!$(this).is(':visible')) $(this).find('ul').hide(); });
});
// uncomment the following line to ensure all sublist are closed,
// however, i strongly recommend this should be done using css
// $('ul ul').hide();
// change cursor for li elements having a sub menu
$('li').each(function(i) {
if ($(this).children('ul').length) { // test if it has a submenu
$(this).css({ cursor: 'pointer' });
// just for this test, i'm going to add a background color to A tags on li's having a submenu
$(this).children('a').css({ backgroundColor: '#f8f800' })
}
});
})
/* this simply hides all submenus outright */
ul ul { display: none; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul>
<li><a>test1</a>
<ul>
<li><a>bleh</a></li>
<li><a>bleh Blah</a>
<ul>
<li><a>blo</a></li>
<li><a>bli</a>
<li><a>blu</a>
<ul>
<li><a>orange</a></li>
<li><a>fruit</a></li>
<li><a>apple</a></li>
</ul>
</li>
<li><a>ble</a>
<ul>
<li><a>gravy</a></li>
<li><a>steak</a></li>
<li><a>bra</a></li>
</ul>
</li>
</li>
<li><a>testCc</a></li>
</ul>
</li>
</ul>
</li>
<li><a>test2</a>
<ul>
<li><a>testPrev</a>
<ul>
<li><a>testA</a></li>
<li><a>testB</a></li>
<li><a>testC</a></li>
</ul>
</li>
<li><a>testNext</a>
<ul>
<li><a>testAa</a></li>
<li><a>testBb</a>
<li><a>testPrev2</a>
<ul>
<li><a>testA1</a></li>
<li><a>testB2</a></li>
<li><a>testC3</a></li>
</ul>
</li>
<li><a>testNext4</a>
<ul>
<li><a>testAa4</a></li>
<li><a>testBb5</a></li>
<li><a>testCc6</a></li>
</ul>
</li>
</li>
<li><a>testCc</a></li>
</ul>
</li>
</ul>
</li>
<li><a>test3</a>
<ul>
<li><a>blah</a></li>
</ul>
</li>
</ul>
You could try:
$(document).ready(function(){
$('ul li.expanded > a')
.attr('data-active','0')
.click(function(event){
$('.submuneu').hide();
if($(this).attr('data-active')==0){
$(this).parent().find('ul').slideToggle('slow');
$(this).attr('data-active','1');
}
else
{
$(this).attr('data-active','0');
}
});
$(document).on('click', 'a.on', function(){
$('a.on').removeClass("active");
$(this).addClass("active");
});
});
Some -code generated- elements need to be "listen" using $(document).on('event', 'element', function(){...});.
Hope it helps.

Set active state on navigation dynamically

I seem to run into this problem frequently and can never find a solution. I have a Wordpress site with a top navigation. Since this is in my header.php, and used on all pages, I cannot hardcode my active menu state for each page.
How can I dynamically set the activate state to work for each page?
Here is my current nav code:
<nav id="main-menu" class="padbot">
<ul id="ce">
<li class="cemenu">About</li>
<li class="cemenu">Consulting</li>
<li class="cemenu">Intelligence</li>
<li class="cemenu">Academy</li>
<li class="cemenu">Blog</li>
<li class="cemenu">Contact</li>
</ul>
I've already setup a CSS class called "active" that has my active state properties. Ideally, what I'm looking for is when your on the "About" page (or any of the other pages), the class I created for the active state will be appended to the current li classes's.
Example:
<li class="cemenu active">About</li>
Thanks!
you could try something along the lines of
<li class="cemenu<?php echo ($_SERVER['PHP_SELF'] == '/about' ? ' active' : '');?>">About</li>
You can do this way:
This will add the active class to the <a> which contains the page from the url.
$(function(){
var url = window.location.href;
var page = url.substr(url.lastIndexOf('/')+1);
$('.cemenu a[href*="'+page+'"]').addClass('active');
});
and if you want to add class to its parent li the replace the last line to this and css class should be like this:
.active a{
css
properties
for active li's a
}
// using closest
$('.cemenu a[href*="'+page+'"]').closest('li').addClass('active');
or
// using parent
$('.cemenu a[href*="'+page+'"]').parent('li').addClass('active');
just tryout the fiddle here
First, there is a css pseudo class prepared for styling 'active' links :
a:active {css}
For your situation, you would have to add this class to your styling :
.active a, a:active {css}
But your needs seems more on the PHP side than the CSS, perhaps someone else will help you with that part. There would be a javascript solution with jQuery, finding the actual location then inject a css selector to the proper element.
Check this article and this other one about wordpress. It will help you.
Stack Overflow references :
How do I target each menu different items on active state in Wordpress
How to add Active states and icons in wordpress wp_nav_menu()
Loosing Nav Active State in Wordpress Dynamic Menu
google search
try something like this:
<?php $pages = array('about' => 'About Us', 'blog' => 'blog') ?>
<ul>
<?php foreach($pages as $url => $page): ?>
<?php $isActive = $_SERVER["REQUEST_URI"] == $url ?>
<li<?php echo $isActive ? ' class="active"' : '' ?>>
<?php echo $page ?>
</li>
<?php endforeach ?>
</ul>
It may be worth looking into using wordpres functions such as get_page_link which would be nicer than using the Server super global as that's not nice. This would also fail if you have wordpress in a folder and not the document root, it's just a simple example to get you started :)
You can try like this
<li class="<?php
if($this_page=='Home'){
echo 'active';
}
?>">
Home
</li>
<li class="<?php
if($this_page=='Contact'){
echo 'active';
}
?>">
Contact
</li>
And then in your home page
$this_page='Home';
And in your contact page
$this_page='Contact';
You could use preg_replace() to add class="active" like this:
ob_start();
echo '<ul>
<li>Page 1</li>
<li>Page 2</li>
</ul>';
$output = ob_get_clean();
$pattern = '~<li><a href="'.$url.'">~';
$replacement = '<li class="active"><a href="'.$url.'">';
echo preg_replace($pattern, $replacement, $output);

Show 2 random li's on from ul - PHP

Hoping someone can help.
I'm building a wordpress site and as part of the design, I've got some 'feature panels' that I'd like to show.
There's a total of 4 li's in the list - but I'd only like to show 2 random ones on every page.
I can do it via CSS by showing / hiding each li based on the page's class - however I'm wondering whether there's a more elegant way of doing the same via PHP?
My HTML is here... I have no idea where to start with the PHP and it seems that I'm Googling the wrong keywords...
<ul id="featurePanels">
<li id="newBoatsPanel">
<h3><a href="#">New Boats<br />
<span>Text</span></a></h3>
</li>
<li id="brokeragePanel">
<h3><a href="#">Brokerage<br />
<span>Text</span></a></h3>
</li>
<li id="newsPanel">
<h3><a href="#">News<br />
<span>Text</span></a></h3>
</li>
<li id="partsPanel">
<h3><a href="#">Parts<br />
<span>Need text here</span></a></h3>
</li>
</ul>
Any pointers would be greatly appreciated.
Thank you.
<?php
$listItems = array(
'<li id="newBoatsPanel">your text here</li>',
'<li id="brokeragePanel">more text here</li>',
'<li id="newsPanel">text text text</li>',
'<li id="partsPanel">Need text here</li>'
);
shuffle($listItems); // shuffles (randomizes the order of the elements)
// print the list
echo '<ul id="featurePanels">' . $listItems[0] . $listItems[1] . '</ul>';
?>
You can use
preg_match_all('/\<li.*?\>.*?\</li\>/i',$html_string,$li_list)
in $li_list you will have an array of li's and now you can shuffle, random, splice, slice or whatever...
and at the end use implode to get the HTML.

How to add class to selective <li> in a generated menu

Hi I am looking for a solution to add a class to every list item <li> which has a child item with a class of <span class="separator"> and a different class to <li> with an anchor link.
I use Joomla and the menu is being generated somewhat like this:
<ul class="menu">
<li class="item1"><span>Home</span></li>
<li class="parent item59"><span class="separator"><span>Demo</span></span></li>
<li class="item62"><span>Article</span></li>
<li id="current" class="parent active item27"><span>CMS</span>
<ul>
<li class="item50"><span>The News</span></li>
<li class="item48"><span>Web Links</span></li>
<li class="item65"><span class="separator"><span /></span></li>
<li class="item49"><span>News Feeds</span></li>
<li class="item66"><span class="separator"><span /></span></li>
<li class="item67"><span class="separator"><span /></span></li>
<li class="item68"><span class="separator"><span /></span></li>
</ul>
</li>
<li class="item71"><span class="separator"><span>Help</span></span></li>
</ul>
What I want is to add class "anclink" or "seplink" to the <li> depending on their child item so that the final output looks like below.
<ul class="menu">
<li class="item1 anclink"><span>Home</span></li>
<li class="parent item59 seplink"><span class="separator"><span>Demo</span></span></li>
<li class="item62 anclink"><span>Article</span></li>
<li id="current" class="parent active item27" anclink><span>CMS</span>
<ul>
<li class="item50 anclink"><span>The News</span></li>
<li class="item48 anclink"><span>Web Links</span></li>
<li class="item65 seplink"><span class="separator"><span /></span></li>
<li class="item49 anclink"><span>News Feeds</span></li>
<li class="item66 seplink"><span class="separator"><span /></span></li>
<li class="item67 seplink"><span class="separator"><span /></span></li>
<li class="item68 seplink"><span class="separator"><span /></span></li>
</ul>
</li>
<li class="item71 seplink"><span class="separator"><span>Help</span></span></li>
</ul>
How can I achieve this using PHP or even a jQuery solution will be fine.
Kindly help.
With jQuery:
$('#menu > li:has( > span.separator )').addClass('seplink');
$('#menu > li:has( > a )').addClass('anclink');
or:
$('#menu > li > span.separator').parent().addClass('seplink');
$('#menu > li > a').parent().addClass('anclink');
EDIT: I was just walking out the door when I left this solution, so I didn't have the chance to note that I'd strongly favor the second solution since it utilizes a valid CSS selector.
It will perform better in browsers that support querySelectorAll.
Without jQuery:
var ul = document.getElementsByClassName("menu");
var li = ul[0].getElementsByTagName("li");
for ( var i = 0; i < li.length; i++ ){
var class = li[i].className;
class += ( li[i].childNodes[0].tagName.toUpperCase() == 'A' ) ? ' anclink' : ' seplink';
li[i].className = class;
}
Edit
So you can eitheir use getElementsByClassName as defined in http://robertnyman.com/2005/11/07/the-ultimate-getelementsbyclassname/ or use another method such as getElementsByTagName (in your case the root of your nested list is the first UL.
For testing purpose I'd advise you to paste this code in the HEAD of your HTML document. Also, you need to call this function once the window is loaded as you want to apply changes on the window's loaded elements.
<script type="text/javascript">
window.onload = function(){
var ul = document.getElementsByTagName("ul")[0];
var li = ul.getElementsByTagName("li");
for ( var i = 0; i < li.length; i++ ){
var myClass = li[i].className;
myClass += ( li[i].childNodes[0].tagName.toUpperCase() == 'A' ) ? ' anclink' : ' seplink';
li[i].className = myClass;
}
};
</script>
Adding a second answer, because I'd advise against loading the entire jQuery library if this is its only purpose.
An alternative would be to use Sizzle, which is the CSS selector engine that is included in jQuery. It is a much smaller download, and as such, may be a decent compromise.
You'd get the library, and use it like this:
var li_span = Sizzle('#menu > li > span.separator'),
li_a = Sizzle('#menu > li > a'),
s = li_span.length,
a = li_a.length;
while( s-- ) {
if( li_span[ s ].className === 'separator' ) {
li_span[ s ].parentNode.className += ' seplink';
}
}
while( a-- ) {
li_a[ a ].parentNode.className += ' anclink';
}
The downloaded file is full size, so you'll want to minify it.
Hey #Patrick and #Nabab none of the solutions worked for me but some how managed to work around with this script and it is working fine in even in IE 6-9 and Firefox. I didnt get chance to check on Opera, Chrome and Safari will try it later.
$(document).ready(function() {
$('ul.menu li:not(:has(li))')
.addClass(function() {
return (
($('span.separator',this).length)
? 'seplink' : (($('a[href]',this).length)
? 'anclink' : null));
});
});
This script was contributed by some generous member yesterday here as an answer to this question. I couldn't get his / her name but don't know why later it disappeared from the list of answers. Luckily I had already copied it by then. I am posting this as an answer as it is working perfectly for me.
I am anyway using the entire jQuery library because there are other aspects of my template which need it. Kindly advise if you guys see any challenge which I may not know, in using this script.

Categories