For theming purposes I need to add a few spans with custom class before, after and around text contained by tag. Fjr now it looks like this:

<li class="sfHover" id="menu-132-1"><a href="/foo" title="bar">Menu Item</a></li>

And I need to have something like this:

<li class="sfHover" id="menu-132-1"><a href="/foo" title="bar"><span class="back"><span class="bg1"></span>Menu Item<span class="foreground"></span></span></a></li>

How can I achieve that?

CommentFileSizeAuthor
#10 template.php.zip1.08 KBLex-DRL
#5 demo.jpg46.4 KBLex-DRL
#5 template.php.zip1.13 KBLex-DRL

Comments

Lex-DRL’s picture

sorry, forgot to add one more code tag. In the first line I meant:

For theming purposes I need to add a few spans with custom class before, after and around text contained by < a > tag. For now it looks like this:

Also, I've already read the topics about adding spans to primary links. But as I'm not PHP coder, I can't make it analogically with Superfish menu. So I'm asking for an advice as direct as possible of where and what should I change/rewrite. I didn't find any block.tpl.php in module's folder so I don't know how to modify generated code through theming.

Lex-DRL’s picture

Status: Active » Needs review

I have found the solution after long time of googling, studying Drupal API and digging into module files, which I will never do if not this issue.
The wayout I found is overriding theme_superfish_build function by site theme.
You need to write this into the template.php of your theme:

// Override theme_superfish_build function provided by Superfish module.
function phptemplate_superfish_build($id, $menu, $depth = -1, $trail = NULL) {
  $output = '';
  foreach ($menu as $menu_item) {
    $mlid = $menu_item['link']['mlid'];
    if ($menu_item['link']['hidden'] == 0) {
      if ($trail && in_array($mlid, $trail)) {
        $class = ' active-trail';
      }
      // Wrap necessary span code around anchor text.
      $menu_item['link']['title'] = '<span class="back"></span><span class="hover"></span><span class="text">' . check_plain($menu_item['link']['title']) . '</span><span class="front"></span>';
      // Define $menu_item['link'] array as that which contains HTML code.
      $menu_item['link']['html'] = TRUE;
      if ((!empty($menu_item['link']['has_children'])) && (!empty($menu_item['below'])) && $depth != 0) {
        $children = theme('superfish_build', $id, $menu_item['below'], $depth, $trail);
        $parent_class = $children ? 'menuparent ' : '';
        $output .= '<li id="menu-'. $mlid .'-'. $id .'"';
        if (!empty($parent_class) || !empty($class)) {
          $output .= ' class="'. $parent_class . $class .'"';
        }
        /*
        Generate menu link using core l() function directly instead of
        theme('menu_item_link', $menu_item['link']) to prevent converting
        "<" and ">" characters to their HTML code.
        */
        $output .= '>'. l($menu_item['link']['title'], $menu_item['link']['href'], $menu_item['link']);
        if ($menu_item['link']['depth'] <= $depth || $depth == -1) {
          if ($children) {
            $output .= "<ul>\n $children \n</ul>\n";
          }
        }
        $output .= "</li>\n";
      }
      else {
        $output .= '<li id="menu-'. $mlid .'-'. $id .'"';
        if (!empty($class)) {
          $output .= ' class="'. $class .'"';
        }
        // The same replacement with l() function one more time.
        $output .= '>'. l($menu_item['link']['title'], $menu_item['link']['href'], $menu_item['link']) .'</li>'."\n";
      }
    }
  }
  return $output;
}

Hope I helped someone in the same trouble.
This is my 1st try of using Drupal API, so I think it's not the best solution. Suggestions are welcomed.

mehrpadin’s picture

Status: Needs review » Fixed

Hey there,

Added in v1.4 :)

Lex-DRL’s picture

Version: 6.x-1.3 » 6.x-1.4
Category: support » bug
Status: Fixed » Needs work

Mehrpadin, thank you for this amazing module and for reply.
I have tested your updated module and it looks like working as expected. One more thanks for new features (item number, first/last etc).
But I found some... kind of bugs:

  • Wrappers are inserted around link but not inside it. I guess, there is usually no need to add extra layers around because this layers won't change on link hover/activation. As you can see, there is also another span after link text in my example from previous post. It's used for overlaying "glossy" in front of buttons. There is no way to make it if you add spans around links as this "glossines" will lay in front of link and users won't be able to press it. I'd better make it to add spans inside link (around everything that link contains), what I actually did.
  • Wrappers aren't added to parent menu items... I don't know why.
  • The length of text field for defining wrapper on block configuration page is too short. I simply can't write all code (all spans) from my previos post because it was trimmed at about 70%. I understand, that there are too much extra spans in my example, but anyway.
  • Optional request. You did exactly as I did - make module to add this code directly into html. This is "dirty" way because finally generated page contains too much extra code (especially for my example), which is bad for semantics.
    As I have googled, usually people add this additional spans dynamically using jquery and something called ".wrapinner" (function?). But as I didn't have a time to dig into JavaScript deeply enough I did it purely by PHP which I at least understand a little.
    It will be great if you realise it using JS, which you understand, as I see.

Here is what I have found of how it is "goodly" done in similar situation.
HTML:

<h2>
	A Movie in the Park:<br />Kung Fu Panda
</h2>

JS:

$(function() {
	$("h2").wrapInner("<span>");
	$("h2 br").before("<span class='spacer'>")
		.after("<span class='spacer'>");
});

And for browser it looks like this:

<h2>
  <span>A Movie in the Park:
    <span class="spacer"></span>
    <br />
    <span class="spacer"></span>
    Kung Fu Panda
  </span>
</h2>

I don't know JS at all - even that I don't understand how to modify this code to suit my desires. Shame on me! :(

Sorry for my broken english and long post and thank you again for SuperFish. It is definetly better than Nice Menus even though I need to use this kind of hack for now to make it work as I need.
I'm marking issue as "needs work". If you think that I'm wrong in my suggestions, mark it fixed back.

Lex-DRL’s picture

StatusFileSize
new1.13 KB
new46.4 KB

I attach to this post a screenshot of Superfish menu I have now with spans described above inserted
inside link to show why I believe that inside is better. "My account" item is hovered. "Add" item is unfolded. Images are used only for background, text is text. All buttons are resizeble to text length.
If someone will need - here is also the same modification to superfish_build function for SF v1.4.

Lex-DRL’s picture

Version: 6.x-1.4 » 6.x-1.5
Status: Needs work » Fixed

Mehrpadin, thank you for last update. :-)
You have done very good improvement by adding all the options instead of replacing one to another. I have tested the new features and they work well.
Marking this issue as fixed because 2 major things are solved.
2 other things are moved here:
#761446: Expand character limit for Wrappers' fields
#761448: Add wrappers dynamically using JavaScript

mehrpadin’s picture

Hey Lex-DRL,

Pajalosta :) but! your code caused a bug: http://drupal.org/node/764152 , any ideas?

Lex-DRL’s picture

Hm... As I said before, I'm not php coder. So I was expecting for some bugs and warned about that. Sorry.


Post is edited - removed previous suggestions.
Lex-DRL’s picture

I have googled and tried to better understand l() and menu_item_link() functions and looks like I have fixed that bug. But before I publish solution here I need some little help with php itself to exclude "dirty" code:

Say, I have existing array $array.
And it already has some elements in it ($array['el1'], $array['el2], $array['el3'] etc). But it doesn't have $array['sub_arr'] yet.
I need to create this sub-sub-element: $array['sub_arr']['var'].
Can I simply create that sub-sub-element at 1 step by defining it's value:
$array['sub_arr']['var'] = 'value';
or I have to create sub-array first:

$array['sub_arr'] = array();
$array['sub_arr']['var'] = 'value';
Lex-DRL’s picture

StatusFileSize
new1.08 KB

Here is a bugfix for 1.5. I'm not familiar with creating patches yet - so I publish it as function override for your theme.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.