3

I have written a custom walker that I am using with wp_nav_menu but I need to iterate through 4 custom classes, and I'm not sure how to do this. Basically, each menu-item <li> needs to be given a class of color1, color2, color3 or color4, cycling back to color1, lather, rinse, repeat, in that order.

Ordinarily I would do this with a $i and a $i++, but how do I do this in the Walker class?

EDIT: My Walker class code:

class Salamander_Advent_Walker extends Walker_page {
function start_el(&$output, $item, $depth, $args) {
    if ( $depth ) {
        $indent = str_repeat("\t", $depth);
    } else {
        $indent = '';
    }

    $advent_thumbnail = get_post_meta($item->ID, 'advent-thumb', true);
    $advent_slug = get_post_meta($item->ID, 'advent-slug', true);
    $advent_oneliner = get_post_meta($item->ID, 'advent-oneliner', true);
    //$description = get_post_meta($item->ID, 'advent-thumb', true);

    $output .= $indent . '
    <li class="active color4">
        <a href="#day'. $advent_slug .'">
            <span class="day">
                <strong>'. $advent_slug .'</strong>
                <span>&nbsp;</span>
            </span>
            <span class="content">
                <small>'. $advent_slug .'</small>
                <img src='. $advent_thumbnail .' width="126" height="91" alt="advent" />
                <strong>'. $advent_oneliner .'</strong>
            </span>
        </a>';                      
}

}

3 Answers 3

1

Use a class variable to keep the 'index' of the colour you wish to display. Increment each time it's used, and check if it goes over, in which case set it back to 1.

class Salamander_Advent_Walker extends Walker_page {
    private $color_idx = 1;
    function start_el(&$output, $item, $depth, $args) {
        if ( $depth ) {
            $indent = str_repeat("\t", $depth);
        } else {
            $indent = '';
        }

        $advent_thumbnail = get_post_meta($item->ID, 'advent-thumb', true);
        $advent_slug = get_post_meta($item->ID, 'advent-slug', true);
        $advent_oneliner = get_post_meta($item->ID, 'advent-oneliner', true);
        //$description = get_post_meta($item->ID, 'advent-thumb', true);

        $output .= $indent . '
        <li class="active color'.$this->color_idx.'">
            <a href="#day'. $advent_slug .'">
                <span class="day">
                    <strong>'. $advent_slug .'</strong>
                    <span>&nbsp;</span>
                </span>
                <span class="content">
                    <small>'. $advent_slug .'</small>
                    <img src='. $advent_thumbnail .' width="126" height="91" alt="advent" />
                    <strong>'. $advent_oneliner .'</strong>
                </span>
            </a>';              
        $this->color_idx++;
        if ($this->color_idx > 4) {
            $this->color_idx = 1
        }
    }

}
3

Create a separate function:

function alternate()
{
    static $i = 0;
    $args = func_get_args();

    return $args[ $i++ % func_num_args() ];
}

In your walker use it like this:

$class = 'color' . alternate( 1, 2, 3, 4 );
// somewhere in your output string:
$output .= '<li class="active ' . $class . '">';
10
  • 2
    The static counter could also be a class var, same thing just less a function.
    – t31os
    Commented Feb 3, 2012 at 17:19
  • 1
    @MarkDuncan I am a fan of atomic functions: one function per task. It makes debugging so much easier. :)
    – fuxia
    Commented Feb 3, 2012 at 17:29
  • Sounds logical, not sure i'd personally use a function for counting alone, but a valid approach nonetheless.
    – t31os
    Commented Feb 3, 2012 at 20:12
  • Sorry appendum, there's a problem with your sample code(the second sample is invalid, as is)...
    – t31os
    Commented Feb 3, 2012 at 20:16
  • @MarkDuncan How exactly?
    – fuxia
    Commented Feb 3, 2012 at 20:27
1

You can do that by setting the incrementing number to a global variable.

function start_el(&$output, $item, $depth, $args) {
    //globalize the variable
    global $ac_color_num;
    //check if it is set, or if it is 4 (to reset to 1)
    if ( !isset($ac_color_num) || $ac_color_num == 4 ) { $ac_color_num = 1; }
    $ac_color_num++
    if ( $depth ) {
        $indent = str_repeat("\t", $depth);
    } else {
        $indent = '';
    }

    $advent_thumbnail = get_post_meta($item->ID, 'advent-thumb', true);
    $advent_slug = get_post_meta($item->ID, 'advent-slug', true);
    $advent_oneliner = get_post_meta($item->ID, 'advent-oneliner', true);
    //$description = get_post_meta($item->ID, 'advent-thumb', true);

    //use $ac_color_num in the output.
    $output .= $indent . '
    <li class="active color' . $ac_color_num . '">
        <a href="#day'. $advent_slug .'">
            <span class="day">
                <strong>'. $advent_slug .'</strong>
                <span>&nbsp;</span>
            </span>
            <span class="content">
                <small>'. $advent_slug .'</small>
                <img src='. $advent_thumbnail .' width="126" height="91" alt="advent" />
                <strong>'. $advent_oneliner .'</strong>
            </span>
        </a>';                      
}
6
  • 1
    There're already too many globals and conflicts are just about to happen. If you add a global, then only if you really have to and even then, you should prefix it.
    – kaiser
    Commented Feb 3, 2012 at 16:02
  • Fair enough. The other answer is more elegant, but mine still solves the problem - not sure if it warrants a downvote... I will say that the likelihood of $color_num conflicting is really low, especially in the scope of any process that this walker would be run in. Commented Feb 3, 2012 at 17:05
  • 1
    By scope I meant the entire process. Added prefix ac_ for 'amanda custom'. Thanks. Commented Feb 3, 2012 at 19:33
  • 2
    Just a sidenote: Instead of calling get_post_meta() several times, you can also do extract( get_post_custom( $post->ID ), EXTR_SKIP ); which gives you the same vars you used with a simple one-liner. Oh, and you're missing a space between the classes: "active color' . $ac_color_num . '".
    – kaiser
    Commented Feb 3, 2012 at 19:44
  • 1
    That's a nice move with get_post_custom - I was just doing a copypasta of her code and adding my stuff in. the lack of a space is so the class is color3 instead of color 3 - I'm just outputting the number. Commented Feb 3, 2012 at 22:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.