1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

[PHP/HTML]Including a navbar with "active" element

Discussion in 'HTML, Graphics & Programming' started by LazyManc, 10 Jan 2006.

  1. LazyManc

    Wise Guy

    Joined: 21 May 2003

    Posts: 1,365

    I don't know if this will be of any use to anyone, but I wrote it a while back and it's been handy on a few different projects. There are most likely better written examples on the net, but I thought i'd share it anyways.

    Normally if you are highlighting the "active" navigation link for the current page (e.g. http://www.alistapart.com/articles/), you can't have the navigation menu as a seperate include because it needs to be slightly different for each page. (Having it as an include is handy because it means that you only need to edit one file should the navigation need updating).

    Basically the code below allows you to have only one navigation list which you can include (using php) in your pages, whilst still retaining the "active" functionality.

    Code:
    <?php
    	// set up the default navigation
    	$nav1 = '<li><a href="addEnquiry.php">Add Enquiry</a></li>';
    	$nav2 = '<li><a href="viewEnquiries.php">View/Edit Enquiries</a></li>';
    	$nav3 = '<li><a href="createReport.php">Create Report</a></li>';
    	$nav4 = '<li><a href="todaysCallbacks.php">Today\'s Callbacks</a></li>';
    	
    	// markup the correct list item as active - $thisPage is provided by the page which is including this file
    	switch ($thisPage)
    	{
    		case 'ELTS :: Add Phone Enquiry':
    			$nav1 = '<li><a href="#" id="current">Add Enquiry</a></li>';
    		break;
    		
    		case 'ELTS :: View/Edit Phone Enquiries':
    			$nav2 = '<li><a href="#" id="current">View/Edit Enquiries</a></li>';
    		break;
    				
    		case 'ELTS :: Create Report':
    			$nav3 = '<li><a href="#" id="current">Create Report</a></li>';
    		break;
    		
    		case 'ELTS :: Today\'s Callbacks':
    			$nav4 = '<li><a href="#" id="current">Today\'s Callbacks</a></li>';
    		break;
    	}
    
    	// draw out the modified navbar with correct section active
    	echo '<ul id="ELTSNav">';
    		echo $nav1;
    		echo $nav2;
    		echo $nav3;
    		echo $nav4;
    	echo '</ul>';
    	
    ?>
    
    
    And then in each page you need to include the menu:

    Code:
    <?php
    	// the name of the current page
    	$thisPage = "ELTS :: Add Phone Enquiry";
    	require_once('navBar.php');
    ?>
    
    Feel free to point out any flaws or improvements.
     
  2. thesubstitute

    Wise Guy

    Joined: 26 Jul 2004

    Posts: 1,073

    Location: Birmingham

    Yeah, lazy as I am I did that for my last site as well, though I stored the navigation in an array with path name, and the script just loops through the array to print out the links, while checking $SERVER['PHP_SELF'] to decide whether it's "current" or not.
     
  3. LazyManc

    Wise Guy

    Joined: 21 May 2003

    Posts: 1,365

    Yeah, using an array is a more sensible way of doing it, I just never got round to it because I didn't have a lot of links ;)
     
  4. robmiller

    Capodecina

    Joined: 26 Dec 2003

    Posts: 16,522

    Location: London

    Code:
    <?php
    
    $nav = array(
        'Home' => '/',
        'About' => '/about',
        'Foo' => '/foo'
    );
    
    foreach($nav as $title => $link) {
    
        $current = ($link == substr($_SERVER['REQUEST_URI'], 0, strrpos($_SERVER['REQUEST_URI'], '?')) ? 'id="current"' : '';
    
        echo '<li><a href="'.$link.'"'.$current.'>'.$title.'</a>';
    
    }
    
    is my preferred method :)
     
  5. thesubstitute

    Wise Guy

    Joined: 26 Jul 2004

    Posts: 1,073

    Location: Birmingham


    Hehe, same as my method except for the $_SERVER['REQUEST_URI'] vs $_SERVER['PHP_SELF'] and id="current" vs class="current" (in case of multiple navigations on same page) that's pretty identical to what I do :D
     
  6. robmiller

    Capodecina

    Joined: 26 Dec 2003

    Posts: 16,522

    Location: London

    Well PHP_SELF just returns the name of the file, so if you're rewriting URIs or the script is in a subdirectory it won't match :)
     
  7. thesubstitute

    Wise Guy

    Joined: 26 Jul 2004

    Posts: 1,073

    Location: Birmingham

    PHP_SELF returns path and filename of script relative to root, so it returns the same value as request_uri in most cases. I'm clueless about apache url rewrite stuff but I do wonder if REQUEST_URI would be affected by it.

    Also I can't use REQUEST_URI on IIS by default (haven't setup apache on local machine yet). Friend's wiki also suffer the same problem (his webhost was IIS) when request_uri was undefined. Seems you have to do extra stuff to fix that problem with IIS to resolve that problem, whilst PHP_SELF worked immediately.

    Any ideas about the differences? The php manual didn't really offer much light.
     
  8. LazyManc

    Wise Guy

    Joined: 21 May 2003

    Posts: 1,365

    The above method only works if the page is requested with a GET method, i.e. there's a question mark in the url.

    This adaption should work with any url:
    Code:
    $nav = array(
        		'Add Record' => 'addRecord.php',
        		'Search Records' => 'searchRecords.php'
    		);
    
    foreach($nav as $title => $link) 
    {
    
    	$current = ($link == substr($_SERVER['REQUEST_URI'], strrpos($_SERVER['REQUEST_URI'], '/')+1, strlen($link))) ? ' id="current"' : '';
    
    	echo '<li><a href="'.$link.'"'.$current.'>'.$title.'</a></li>' . "\n";
    
    }
    
     
  9. roboffer

    Sgarrista

    Joined: 18 Oct 2002

    Posts: 9,599

    Location: Sunderland

    Im building a custom .net control at the moment that does something along these lines from an XML document
     
  10. robmiller

    Capodecina

    Joined: 26 Dec 2003

    Posts: 16,522

    Location: London

    1. It works regardless of whether there's a query string, it just removes the query string if there is one.
    2. Almost all pages are fetched via GET, whether they have a query string or not. Examine an HTTP request sometime; telnet to google.com:80 and type:

      Code:
      GET / HTTP/1.1
      Host: google.com
      
      See? No question mark, GET method. 99.9% of the time you request a page, static or dynamic, question mark or no question mark, it's via GET.
     
  11. LazyManc

    Wise Guy

    Joined: 21 May 2003

    Posts: 1,365

    Ok, I get what you're saying, but from my understanding:

    Code:
    strrpos($_SERVER['REQUEST_URI'], '?')
    
    gives the number of characters upto the first "?"

    so
    Code:
    substr($_SERVER['REQUEST_URI'], 0, strrpos($_SERVER['REQUEST_URI'], '?'))
    
    gives the whole request string up until the first "?"

    e.g. /news/20050401/article103.php or whatever.

    so if you're comparing that against $link, then it's never going to match unless you put the full directory path in the array?

    I may just not understand your directory structure.


    Is there a less convoluted way of getting just say "addRecord.php" than using:
    Code:
    substr($_SERVER['REQUEST_URI'], strrpos($_SERVER['REQUEST_URI'], '/')+1, strlen($link)))
    
    bearing in mind that the file that calls the page may be an include?
     
  12. robmiller

    Capodecina

    Joined: 26 Dec 2003

    Posts: 16,522

    Location: London

    It finds the last ? in the URL, note strrpos, not strpos. I've not tested it, but it should just return false should there not be a ? in the URL, and the substr should return the whole string. If PHP does something stupid like interpreting FALSE as 0, you can just cheat and do

    Code:
    if(!empty($_SERVER['QUERY_STRING'])) {
        $_SERVER['REQUEST_URI'] = str_replace('?'.$_SERVER['QUERY_STRING'], '', $_SERVER['REQUEST_URI']);
    }
    
    It's easier if you're not using any kind of rewrites - you can just use $_SERVER['PHP_SELF'] - but I virtually always am, so there's no point :)
     
  13. Dj_Jestar

    Caporegime

    Joined: 18 Oct 2002

    Posts: 28,818

    Location: Back in East London

    Just a note.. PHP_SELF can be tainted, so try to avoid using it (in which robmiller's example shows how)
     
  14. punky_munky

    Mobster

    Joined: 17 Oct 2002

    Posts: 2,959

    Just thought I'd bump this to say I used LazyManc's code as it seemed most logical to myself.

    This is a useful thread, perhaps it should be archived. :)