1

I have a dynamically generated variable that contains the currently selected city by the user. The format of the string is exactly the same as the href in the navigation menu below except without the prefix /city/.

Example:
    $user_city = 'london';
    $user_city = 'edinburgh';
...

I have the navigation menu below and I want to highlight the currently selected city, that is I want to add a class "active" to the currently selected city.

<ul>
    <li class="first"><a href="/city/all">All</a></li>
    <li><a href="/city/london">London</a></li>
    <li><a href="/city/liverpool">Liverpool</a></li>
    <li><a href="/city/edinburgh">Edinburgh</a></li>
    <li class="last"><a href="/city/glasgow">Glasgow</a></li>
</ul>

I know I could achieve this by putting each list item into an if statement looking whether $user_city equals the string in the href attribute. But I guess there must be a much smarter way?

Thanks in advance

maze
  • 137
  • 2
  • 7
  • 1
    Can you modify the function generating the List? If so, can you show it's source please? Is the menu structure always like shown above or can there be deviations from li item and a structure? Is the menu in a variable too or part of a full document? – Gordon Nov 02 '10 at 13:05
  • No, I can't modify it. All your answers work great and as there won't be much changes to the city list, I'm happy to go with it. Thanks a lot to all of you. – maze Nov 02 '10 at 13:35

4 Answers4

1

If you have access to the menu generating function, you can do something like this:

$cities   = array('London', 'Liverpool', 'Edingburgh', 'Glasgow');
$userCity = 'London';
echo '<ul><li class="first"><a href="/city/all">All</a></li>', PHP_EOL;
foreach($cities as $city) {
    printf(
        '<li><a href="/city/%s"%s>%s</a></li>%s',
        strtolower(htmlentities($city)),
        $userCity === $city ? ' class="active' : '', // conditional
        (htmlentities($city)),
        PHP_EOL
    );
}
echo '</ul>';

In other words, add a conditional that checks whether the current city stored in $userCity is the one currently printed on screen and if so add a class to it.

Give me a comment if you update your question with your menu generating function. I will show you how to modify it with a conditional then (if you cant figure it from the above now).


If you have to modify the menu after it's generated and you can be sure the structure is always the same, then you can simply str_replace

$menu = 'a string containing your menu HTML';    
$city = 'london';
echo str_replace(
    sprintf('<li><a href="/city/%s">', $city),
    sprintf('<li><a href="/city/%s" class="active">', $city),
    $menu
);

If you need more difficult string replacements, consider using an HTML parser.

Community
  • 1
  • 1
Gordon
  • 312,688
  • 75
  • 539
  • 559
1

Check every link isn't a best way. You can optimize it with jQuery:

$(document).ready(function(){
   $('a [href="/city/<?= $user_city ?>"]').addClass('active');
});
Alex Pliutau
  • 21,392
  • 27
  • 113
  • 143
0

you can try like this:

<?php
  $cities = array('london' => '', 'edinburgh' => '');
  $cities[$user_city] = 'active';
?>

<ul>
<li class="first"><a href="/city/all">All</a></li>
<li><a href="/city/london" class="<?php echo $cities['london']; ?>">London</a></li>
<li><a href="/city/edinburgh" class="<?php echo $cities['edinburgh']; ?>">Edinburgh</a></li>
</ul>
egis
  • 1,404
  • 2
  • 11
  • 24
0

This is what I just wrote and it should do the trick. But it will need modification to work with your script.

<?php

  function list_cities($selected_cities = array()) {

    // The HTML attribute
    $class = null;

    // A list of all the cities
    $cities = array('london', 'liverpool', 'edinburgh', 'glasgow');

    // Used to find the last city
    $i = 1;

    // An alias of the selected cities
    $chosen = array();

    // Put the city name in as the array's key
    foreach( $selected_cities as $city ) {
      $chosen[$city] = $city;
    }

    // The first link
    echo '<li class="first"><a href="/city/all">All</a></li>' . "\n";

    // Loop through all the cities
    foreach( $cities as $city ) {

      // If we are on the last item
      $class .= ($i == count($cities)) ? 'last ' : null;

      // If this is a chosen city
      $class .= (isset($chosen[$city])) ? 'active ' : null;

      // Create the list item
      echo '<li class="' . rtrim($class) . '"><a href="/city/' . $city . '">' . ucfirst($city) . '</a></li>' . "\n";

      // Go to the next id
      $i++;

      // Reset the class
      $class = null;
    }
  }

?>


<ul>
  <?php list_cities(array('liverpool', 'glasgow')) ?>
</ul>
Baylor Rae'
  • 3,995
  • 20
  • 39