Menu Item Count

I am writing my own theme and I came up on a PHP problem. Here is the original default.php i was working with which worked well for what it did:


public function process($module, $element) {
  self::_process($module, $element->first('ul:first'));
  return $element;
}


/*
  Function: _process


  Returns:
   Void
*/
protected static function _process($module, $element, $level = 0) {


  if ($level == 0) {
   $element->attr('class', 'menu '.$module->menu_style);

  } else {
   $element->addClass('level'.($level + 1));
  }


  foreach ($element->children('li') as $li) {


   // is active ?
   if ($active = $li->attr('data-menu-active')) {
    $active = $active == 2 ? ' active current' : ' active';
   }

   // is parent ?
   $ul = $li->children('ul');
   $parent = $ul->length ? ' parent' : null;



   // set class in li
   $li->attr('class', sprintf('level%d item%s'.$parent.$active, $level + 1, $li->attr('data-id')));

   // set class in a/span
   foreach ($li->children('a,span') as $child) {


    // get title
    $title = $child->first('span:first');


    // set subtile
    $subtitle = $title ? explode('||', $title->text()) : array();

    if (count($subtitle) == 2) {
     $li->addClass('hassubtitle');
     $title->html(sprintf('<span class="title">%s</span><span class="subtitle">%s</span>', trim($subtitle[0]), trim($subtitle[1])));
    }


    // set image
    if ($image = $li->attr('data-menu-image')) {
     $title->prepend(sprintf('<span class="icon" style="background-image: url(\\'%s\\');"> </span>', $image));
    }


    $child->addClass(sprintf('level%d'.$parent.$active, $level + 1));
   }


   // process submenu
   if ($ul->length) {
    self::_process($module, $ul->item(0), $level + 1);
   }
  }


The problem is, I am changing my menu style and I now need to differentiate between the first menu item, the last, and any in between (to add in a CSS class). So here is what I did with the code but it is not working:


public function process($module, $element) {
  self::_process($module, $element->first('ul:first'));
  return $element;
}


/*
  Function: _process


  Returns:
   Void
*/
protected static function _process($module, $element, $level = 0) {


  if ($level == 0) {
   $element->attr('class', 'menu '.$module->menu_style);

  } else {
   $element->addClass('level'.($level + 1));
  }


  foreach ($element->children('li') as $li) {


   // is active ?
   if ($active = $li->attr('data-menu-active')) {
    $active = $active == 2 ? ' active current' : ' active';
   }

   // is parent ?
   $ul = $li->children('ul');
   $parent = $ul->length ? ' parent' : null;

                        // is first or last ?
   $lis = $element->children("ul");
   for($forl=0,$imax=count($lis);


                        $forl<$imax;$forl++){
   $forl = array();
   if (forl==0) $position_n = 'first';
   elseif ($forl==$imax-1) $position_n = 'last';
   else $position_n = null;
   }


   // set class in li
   $li->attr('class', sprintf('level%d item%s'.$parent.$active, $level + 1, $li->attr('data-id'), $position_n));

   // set class in a/span
   foreach ($li->children('a,span') as $child) {


    // get title
    $title = $child->first('span:first');


    // set subtile
    $subtitle = $title ? explode('||', $title->text()) : array();

    if (count($subtitle) == 2) {
     $li->addClass('hassubtitle');
     $title->html(sprintf('<span class="title">%s</span><span class="subtitle">%s</span>', trim($subtitle[0]), trim($subtitle[1])));
    }


    // set image
    if ($image = $li->attr('data-menu-image')) {
     $title->prepend(sprintf('<span class="icon" style="background-image: url(\\'%s\\');"> </span>', $image));
    }


    $child->addClass(sprintf('level%d'.$parent.$active, $level + 1));
   }


   // process submenu
   if ($ul->length) {
    self::_process($module, $ul->item(0), $level + 1);
   }
  }


Could you please explain what “is not working means” ? An error? A result that isn’t what you want? And if so, what is the result you’re getting and what’s wrong with it?

Sorry for not being more clear. The goal is to have the first menu item be appended with the class “first” and the last menu item be appended with the class “last”. There will be other class elements present which are currently working with the code as it is such as the items listed under //set class for li. so to add in this first and last class addition where appropriate, I tried to add in a variable, $position_n in that line. And I defined it in the lines above - under //is first or last? - but when I check, it does not append the class of the menu items with first or last in the appropriate menu items (not in any of them, but more specifically, not in the first and last menu item.

It may help you to understand what I’m doing by explaining the goal. I have a boxed menu item that floats in my header. To make it more graphically pleasing, the first and last menu item need a different style, one that rounds the edges (left edges for first). See pics

Here is an image of what I am trying to achieve by adding the class the first and last menu item:

And then here is what I get on my actual website because of not being able to append that class:


// is first or last ?
$lis = $element->children("ul");
for ($forl=0,$imax=count($lis); $forl<$imax; $forl++) {
  [COLOR="#FF0000"][B]$forl = array();[/B][/COLOR]
   [COLOR="#FF0000"][B]if (forl==0) $position_n = 'first';[/B][/COLOR]
   elseif ($forl==$imax-1) $position_n = 'last';
   else $position_n = null;
}

I don’t understand the first line I marked in red. If you put an empty array in $forl, that for loop doesn’t work anymore does it?
And in the second red marked line there is a $ missing.

Thanks for the tip on the empty array. I just read a book on PHP last week so I am still pretty new at this stuff. I will keep that in mind from now on. And I can’t believe I forgot the “$” sign. Thanks for pointing that out too.

I made the corrections and nothing. But then I looked at the sprintf and realized that was off too. I changed:


$li->attr('class', sprintf('level%d item%s'.$parent.$active, $level + 1, $li->attr('data-id'), $position_n));

To:


$li->attr('class', sprintf('level%d item%s '. $position_n .$parent.$active, $level + 1, $li->attr('data-id')));

That seems to have helped get me 1/3 of the way there. What I mean is that I am now successfully appending the class for all LIs. Unfortunately, they are all being appended with “first” regardless of whether they are the first, middle or last. See the pic below for the developer tools window of the page’s code:

So it appears that something is wrong in my lines below and that is causing only the class “first” to be added to every LI:


$lis = $element->children("li");	
for($forl=0,$imax=count($lis);
$forl<$imax;$forl++){
	if ($forl==0) $position_n = 'first';
	elseif ($forl==$imax-1) $position_n = 'last';
	else $position_n = null;
}

Any suggestions on this? And thanks again for your helping a newbie.

Nick

Can you explain what you are doing in that loop? Because I’ve read it a couple of times, but I can’t figure out how you’re deciding if the li your handling is first, middle or last.